i forgot about goto until gemini reshowed me

This commit is contained in:
Andrew Haynes
2026-02-26 15:46:54 -05:00
parent 9cc6742476
commit 5e06151e84
2 changed files with 69 additions and 89 deletions
-3
View File
@@ -1,5 +1,4 @@
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.16)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_C_STANDARD 23) set(CMAKE_C_STANDARD 23)
set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
@@ -10,5 +9,3 @@ set(SOURCES
) )
add_executable(tic_tac_toe ${SOURCES}) add_executable(tic_tac_toe ${SOURCES})
target_include_directories(tic_tac_toe PRIVATE include)
+69 -86
View File
@@ -1,118 +1,101 @@
#include <stdio.h>
#include <string.h> #include <string.h>
#include <termios.h> #include <termios.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
const char p1 = 'x', p2 = 'o'; const char p1 = 'x', p2 = 'o';
char temp = p1; char temp = 'x';
char status[32]; char buf[9] = { " " };
char buf[9]; static const unsigned char wins[8][3] = { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 },
{ 0, 3, 6 }, { 1, 4, 7 }, { 2, 5, 8 },
{ 0, 4, 8 }, { 2, 4, 6 } };
bool int
check_line(const char id) check_line(const char id)
{ {
const int wins[8][3] = { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 },
{ 0, 3, 6 }, { 1, 4, 7 }, { 2, 5, 8 },
{ 0, 4, 8 }, { 2, 4, 6 } };
for (int i = 0; i < sizeof(wins) / sizeof(wins[0]); i++) for (int i = 0; i < sizeof(wins) / sizeof(wins[0]); i++)
{ {
if ((buf[wins[i][0]] == id && buf[wins[i][1]] == id && if ((buf[wins[i][0]] == id && buf[wins[i][1]] == id &&
buf[wins[i][2]] == id)) buf[wins[i][2]] == id))
{ {
return true; return 1;
} }
} }
return false; return 0;
} }
void void
set_raw_mode(bool enable) draw_board()
{ {
static struct termios oldt, newt; char divider[] = " - + - + -\n";
if (enable) write(1, "\033[H\033[J", sizeof("\033[H\033[J") - 1);
for (int i = 0; i < 9; i += 3)
{ {
tcgetattr(STDIN_FILENO, &oldt); char row[] = " 0 | 0 | 0\n";
newt = oldt; row[1] = buf[i];
newt.c_lflag &= ~(ICANON | ECHO); row[5] = buf[i + 1];
tcsetattr(STDIN_FILENO, TCSANOW, &newt); row[9] = buf[i + 2];
write(1, row, sizeof(row) - 1);
if (i < 6) write(1, divider, sizeof(divider) - 1);
} }
else write(1, "Current Player: ", 16);
{ write(1, &temp, 1);
tcsetattr(STDIN_FILENO, TCSANOW, &oldt); write(1, "\n", 1);
}
}
bool
update_status()
{
auto p1_check = check_line(p1);
auto p2_check = check_line(p2);
if (p1_check || p2_check)
{
(p1_check ? (void)strncpy(status, "Game Over! Player 1 wins!\n",
sizeof(status))
: (void)strncpy(status, "Game Over! Player 2 wins!\n",
sizeof(status)));
return true;
}
int count = 0;
for (int i = 0; i < sizeof(buf) / sizeof(buf[0]); i++)
{
if (buf[i] != ' ') count++;
}
if (count == sizeof(buf) / sizeof(buf[0]))
{
(void)strncpy(status, "Game Over! It's a tie!\n",
sizeof(status));
return true;
}
snprintf(status, sizeof(status), "Current Player: %c\n", temp);
return false;
}
bool
process_input()
{
char ch;
while (read(STDIN_FILENO, &ch, 1))
{
if (ch == 'q') return false;
if (ch < '1' || ch > '9') continue;
int index = ch - '1';
if (buf[index] != ' ') continue;
buf[index] = temp;
temp = (temp == p1) ? p2 : p1;
return true;
}
return true;
} }
int int
main() main()
{ {
bool game_over; static struct termios oldt, newt;
for (int i = 0; i < sizeof(buf) / sizeof(buf[0]); i++) buf[i] = ' '; tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
set_raw_mode(true); newt.c_lflag &= ~(ICANON | ECHO);
printf("\033[?25l"); tcsetattr(STDIN_FILENO, TCSANOW, &newt);
do write(1, "\033[?25l", sizeof("\033[?25l") - 1);
while (1)
{ {
game_over = update_status(); if (check_line(p1))
printf("\033[H\033[J"); {
printf(" %c | %c | %c\n", buf[0], buf[1], buf[2]); break;
printf(" - + - + -\n"); }
printf(" %c | %c | %c\n", buf[3], buf[4], buf[5]); if (check_line(p2))
printf(" - + - + -\n"); {
printf(" %c | %c | %c\n", buf[6], buf[7], buf[8]); write(1, "P2 wins!\n", sizeof("P2 wins!\n") - 1);
printf("%s", status); break;
fflush(stdout); }
} while (!game_over && process_input()); int filled = 0;
printf("Press any key to quit.\n"); while (filled < 9)
{
draw_board();
char ch;
read(0, &ch, 1);
if (ch == 'q') break;
int idx = ch - '1';
if (ch >= '1' && ch <= '9' && buf[idx] == ' ')
{
buf[idx] = temp;
if (check_line(temp))
{
draw_board();
write(1, &temp, 1);
write(1, " wins!\n",
sizeof(" wins!\n") - 1);
goto end;
}
temp = (temp == p1) ? p2 : p1;
filled++;
}
}
write(1, "It's a tie!\n", sizeof("It's a tie!\n") - 1);
break;
}
end:
write(1, "Press any key to quit.\n",
sizeof("Press any key to quit.\n") - 1);
char dummy; char dummy;
read(STDIN_FILENO, &dummy, 1); read(STDIN_FILENO, &dummy, 1);
printf("\033[?25h"); write(1, "\033[?25h", 5);
set_raw_mode(false); tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
return 0;
} }