/* SPDX-License-Identifier: GPL-2.0-only */ /* * AnnaConnect is a silly little text-based connect 4 game c: * Copyright (C) 2025 Anna Snoeijs. anna.snoeijs@hotmail.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "ui.h" #include #include #include "macros.h" #define BOARD_WIDTH_CHARS ( 3 * board.columns + 6 ) #define SCOREBOARD_OFFSET 5 #define SCOREBOARD_WIDTH 27 #define SCOREBOARD_HEIGHT 9 void initBoard( const board_t board ){ for( int i = SCOREBOARD_HEIGHT - ( board.rows + 2 ); i > 0; i-- ) putchar( '\n' ); printf( "\n " ); for( int column = 0; column < board.columns; column++ ) printf( "%2d ", column + FIRST_NUMBER ); putchar( '\n' ); for( int row = board.rows - 1; row > -1; row-- ){ // begin row printf( "%2d " , row + FIRST_NUMBER ); for( int column = 0; column < board.columns; column++ ) printf( "[ ]" ); // end of row printf( "%2d" , row + FIRST_NUMBER ); switch( row ){ } putchar( '\n' ); } // end of board printf( " " ); for( int column = 0; column < board.columns; column++ ) printf( "%2d ", column + FIRST_NUMBER ); #define SCOREBOARD_LINE_END "\033[B\033["XSTR(SCOREBOARD_WIDTH)"D" printf("\033["XSTR(SCOREBOARD_OFFSET)"C\033["XSTR(SCOREBOARD_HEIGHT)"A" "┌───────────────┬────┬────┐"SCOREBOARD_LINE_END "│ player │ 0 │ 1 │"SCOREBOARD_LINE_END "├───────────────┼────┼────┤"SCOREBOARD_LINE_END "│ vertical │ │ │"SCOREBOARD_LINE_END "│ horizontal │ │ │"SCOREBOARD_LINE_END "│ diagonal up │ │ │"SCOREBOARD_LINE_END "│ diagonal down │ │ │"SCOREBOARD_LINE_END "├───────────────┼────┼────┤"SCOREBOARD_LINE_END "│ total │ │ │"SCOREBOARD_LINE_END "└───────────────┴────┴────┘"SCOREBOARD_LINE_END ); #undef SCOREBOARD_LINE_END putchar( '\n' ); putchar( '\n' ); } void updateBoard( const wins_t wins, const board_t board, const int column ){ int height = board.height [ column ]; printf( "\033[%dA\033[%dC%c\033[%dB", height + 3, column * 3 + 4, '0' + !!( board.player ), height + 1 ); printf( "\r\033[7A\033[%dC" "%3d │%3d\033[B\033[8D" "%3d │%3d\033[B\033[8D" "%3d │%3d\033[B\033[8D" "%3d │%3d\033[2B\033[8D" "%3d │%3d\033[2B" ,( 3 * board.columns + 6 ) + SCOREBOARD_WIDTH - 8 ,wins.count0.vertical, wins.count1.vertical ,wins.count0.horizontal, wins.count1.horizontal ,wins.count0.diagonalUp, wins.count1.diagonalUp ,wins.count0.diagonalDown, wins.count1.diagonalDown ,wins.count0.total, wins.count1.total ); printf( "\033[2K\n" ); } int askColumn( const board_t board ){ int column; for(;;){ printf( "Wher player %d put? ", board.player ); printf( "\033[K" ); // clear everything after cursor fflush( stdout ); column = -1; for( char ch = '0'; ch != '\n'; read( STDIN_FILENO, &ch, 1 ) ){ if( ch >= '0' && ch <= '9' ){ if( column == -1 ) column = 0; else column *= 10; if( column >= 0 ) column += ( int )( ch - '0' ); } else { column = -2; } } column -= FIRST_NUMBER; if( column >= 0 && column < board.columns ) if( board.height [ column ] < board.rows ) return column; else printf( "\033[2Apls enter a column that ain't full" ); else printf( "\033[2Apls enter valid column" ); printf( "\033[K\n" ); } } #undef BOARD_WIDTH_CHARS #undef SCOREBOARD_OFFSET #undef SCOREBOARD_WIDTH #undef SCOREBOARD_HEIGHT