三子棋(井字棋)的c语言实现
首先声明:此项目对cxk的粉丝不太友好,望各位周知
项目主要步骤
- 我们要先初始化棋盘,并将其打印出来
- 我们要打印一个菜单,供玩家选择
- 实现游戏核心,玩家移动和电脑移动两个函数
- 每走一步,就要判断是否获胜,所以要有一个判断是否获胜的函数
- 最后如果棋盘已走满,仍未有人获胜,将是平局
函数模块分析
首先,我们要有一个进入游戏的菜单,供玩家选择
void menu(void) //开始游戏菜单
{
printf("**********三子棋游戏**********\n");
printf("* 1.play *\n");
printf("* 0.exit *\n");
printf("******************************\n");
}
接着,初始化棋盘
void init_board(char board[ROW][COL], int row, int col) //初始化棋盘,每个元素都为空格
{
for (row = 0; row < ROW; row++)
{
for (col = 0; col < COL; col++)
{
board[row][col] = ' ';
}
}
}
初始化完棋盘之后,我们要将棋盘打印出来
void show_board(char board[ROW][COL], int row, int col) //打印棋盘
{
int i = 0;
for (i = 0; i < row; i++)
{
printf("%c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
if (i != row - 1)
printf("——|——|——\n");
}
printf("\n");
}
棋盘效果图如下:
接下来,我们来编写玩家移动函数
void player_move(char board[ROW][COL], int row, int col) //玩家移动,棋子为X
{
printf("X代表你的棋子,O代表电脑的棋子!\n");
printf("请输入你要走的点的坐标,例如1,1\n");
while (1)
{
int i;
char str[128];
scanf("%s", str);
if (str[0] < '0' || str[0] >'9' || str[2] < '0' || str[2] > '9')
{
printf("输入格式错误!");
continue;
}
if (str[3] != NULL)
{
printf("输入格式错误!\n");
continue;
}
if (int(str[0] - '0') < 1 || int(str[0] - '0') > 3 || str[1] != ',' || int(str[2] - '0') < 1 || int(str[2] - '0') > 3)
{
printf("输入格式错误!\n");
continue;
}
row = int(str[0] - '0');
col = int(str[2] - '0');
row -= 1;
col -= 1;
if (board[row][col] != ' ')
{
printf("该坐标已有棋子,请重新输入!\n");
}
if (board[row][col] == ' ')
{
board[row][col] = 'X';
break;
}
}
}
考虑到程序的健壮性,我们要将用户所输入的任何值都考虑到,所以我用了一个数组来表示用户的输入,以此保证程序不会崩溃。因此,用户只能按照如1,1这样的格式输入坐标点。同时,即使格式输入正确,也要保证用户输入的坐标原先是没有棋子的。用户的棋子我们用X表示。
玩家的函数编写完成之后,我们就要来编写电脑移动的函数了
void computer_move(char board[ROW][COL], int row, int col) //电脑移动 棋子为O
{
while (1)
{
row = rand() % 3;
col = rand() % 3;
if (board[row][col] == ' ')
{
board[row][col] = 'O';
break;
}
}
}
电脑我们用rand()
函数来确定坐标,但是不要忘记%3,确保所生成的坐标在数组范围内,还应注意,要加上srand((unsigned)time(NULL));
,确保每次随机生成的值都不同。电脑的棋子我们用O表示。
接下来,我们要判断是否获胜
char check_win(char board[ROW][COL], int row, int col) //判断是否获胜
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
return board[i][0];
}
for (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[0][j] != ' ')
return board[0][j];
}
if ((board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' '))
return board[0][0];
else if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
return board[0][2];
else if (is_full(board, ROW, COL) & 1 == 1)
return 'h';
else
return 'p';
}
如果横着三条线或竖着三条线或两个对角线已经有三个棋子连在一起(三个X或三个O连在一起),我们就返回这条线上的棋子(X或O),通过返回的棋子来判断谁赢。如果棋盘下满后仍未分出胜负,则返回‘h’,判定平局。如果还没分出结果,就返回’p’。
判断胜负的函数中用到了判断棋盘是否下满的函数is_full(),那么接下来我们就来编写这个函数
int is_full(char board[ROW][COL], int row, int col) //判断棋盘是否已经满了,若满返回1,
{ //反之返回0
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
如果数组当中已经没有空格字符了就判定棋盘已下满,返回1。
开始已经声明过了,对cxk的粉丝不太友好,如果你是cxk的粉丝,请不要继续往下看
接下来编写game()函数,来输出结果
void game(void)
{
char board[ROW][COL];
char ch;
init_board(board, ROW, COL);
srand((unsigned)time(NULL));
show_board(board, ROW, COL);
while (1)
{
player_move(board, ROW, COL);
ch = check_win(board, ROW, COL);
show_board(board, ROW, COL);
if (ch != 'p')
break;
computer_move(board, ROW, COL);
ch = check_win(board, ROW, COL);
show_board(board, ROW, COL);
if (ch != 'p')
break;
}
if (ch == 'O')
{
printf("呵呵,你输了,你下棋真像cxk!\n");
}
else if (ch == 'X')
printf("恭喜你!你赢了,你比cxk强一点!\n");
else if (ch == 'h')
{
printf("平局,你是cxk\n");
}
}
首先我们调用初始化棋盘和打印棋盘的函数,然后进入while(1)死循环,在while()循环中玩家先走棋,判断是否已经赢了,打印棋盘,将判断是否获胜的函数check_win()的返回值赋给ch
,如果ch
等于 ‘p’,则表示没有获胜,也没有平局,那么循环继续,轮到电脑走棋,电脑走棋同理,直到ch
不等于‘p’。如果ch
不等于’p’,则返回‘X’、‘O’或‘h’,'X’表示玩家获胜,'O’表示电脑获胜,'h’则表示平局。
最后,主函数来调用
int main(void)
{
int choose;
do
{
menu();
printf("请输入你的选择—>");
scanf("%d", &choose);
switch (choose)
{
case 1:
game();
break;
case 0:
break;
default:
printf("输入错误!请重新输入0或1!\n");
break;
}
} while (choose);
return 0;
}
项目整体源码
到此,我们用c语言写的一个简单的小游戏三子棋就完成了,下面附上源码,供大家参考和指正
源码:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#define ROW 3 //棋盘的长度
#define COL 3 //棋盘的宽度
int is_full(char board[ROW][COL], int row, int col);
void menu(void) //开始游戏菜单
{
printf("**********三子棋游戏**********\n");
printf("* 1.play *\n");
printf("* 0.exit *\n");
printf("******************************\n");
}
void init_board(char board[ROW][COL], int row, int col) //初始化棋盘,每个元算都为空格
{
for (row = 0; row < ROW; row++)
{
for (col = 0; col < COL; col++)
{
board[row][col] = ' ';
}
}
}
void show_board(char board[ROW][COL], int row, int col) //打印棋盘
{
int i = 0;
for (i = 0; i < row; i++)
{
printf("%c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
if (i != row - 1)
printf("——|——|——\n");
}
printf("\n");
}
void player_move(char board[ROW][COL], int row, int col) //玩家移动,棋子为X
{
printf("X代表你的棋子,O代表电脑的棋子!\n");
printf("请输入你要走的点的坐标,例如1,1\n");
while (1)
{
int i;
char str[128];
scanf("%s", str);
if (str[0] < '0' || str[0] >'9' || str[2] < '0' || str[2] > '9')
{
printf("输入格式错误!");
continue;
}
if (str[3] != NULL)
{
printf("输入格式错误!\n");
continue;
}
if (int(str[0] - '0') < 1 || int(str[0] - '0') > 3 || str[1] != ',' || int(str[2] - '0') < 1 || int(str[2] - '0') > 3)
{
printf("输入格式错误!\n");
continue;
}
row = int(str[0] - '0');
col = int(str[2] - '0');
row -= 1;
col -= 1;
if (board[row][col] != ' ')
{
printf("该坐标已有棋子,请重新输入!\n");
}
if (board[row][col] == ' ')
{
board[row][col] = 'X';
break;
}
}
}
void computer_move(char board[ROW][COL], int row, int col) //电脑移动 棋子为O
{
while (1)
{
row = rand() % 3;
col = rand() % 3;
if (board[row][col] == ' ')
{
board[row][col] = 'O';
break;
}
}
}
char check_win(char board[ROW][COL], int row, int col) //判断是否获胜
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
return board[i][0];
}
for (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[0][j] != ' ')
return board[0][j];
}
if ((board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' '))
return board[0][0];
else if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
return board[0][2];
else if (is_full(board, ROW, COL) & 1 == 1)
return 'h';
else
return 'p';
}
int is_full(char board[ROW][COL], int row, int col) //判断棋盘是否已经满了,若满返回1,
{ //反之返回0
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
void game(void)
{
char board[ROW][COL];
char ch;
init_board(board, ROW, COL);
srand((unsigned)time(NULL));
show_board(board, ROW, COL);
while (1)
{
player_move(board, ROW, COL);
ch = check_win(board, ROW, COL);
show_board(board, ROW, COL);
if (ch != 'p')
break;
computer_move(board, ROW, COL);
ch = check_win(board, ROW, COL);
show_board(board, ROW, COL);
if (ch != 'p')
break;
}
if (ch == 'O')
{
printf("呵呵,你输了,你下棋真像cxk!\n");
}
else if (ch == 'X')
printf("恭喜你!你赢了,你比cxk强一点!\n");
else if (ch == 'h')
{
printf("平局,你是cxk\n");
}
}
int main(void)
{
int choose;
do
{
menu();
printf("请输入你的选择—>");
scanf("%d", &choose);
switch (choose)
{
case 1:
game();
break;
case 0:
break;
default:
printf("输入错误!请重新输入0或1!\n");
break;
}
} while (choose);
return 0;
}