学习C语言已经有一小段时间了,这是我编写的第一个有意义的小程序。
要编写井字棋,我们要先从开始界面开始编写。这个开始界面可以根据个人喜好进行改造。
void menu()//初始界面
{
printf("*****************************************\n");
printf("*****************************************\n");
printf("************ 1.play game *************\n");
printf("************ 0.quit *************\n");
printf("*****************************************\n");
printf("*****************************************\n");
}
然后我们开始编写main函数,首先要让这个初始界面真正发挥作用。通过下面的程序可以做到输入1继续执行程序,输入0退出,输入别的数字和字符会提示并让你再次输入。
int main()
{
int input = 0;
menu();
scanf("%d", &input);
if (input == 1)
{
printf("开始游戏\n");
}
else if(input==0)
{
printf("退出游戏\n");
return 0;
}
else
{
printf("输入错误\n");
return 0;
}
//初始界面
然后开始编写游戏主程序,要实现井字棋要先打印棋盘,之后实现玩家下棋、机器自动下棋,最后再次打印棋盘并判断胜负。
在棋盘第一次被打印出来之前要先初始化棋盘,这里空棋盘使用的是“ ”
void initboard(char board[row][col],int ROW,int COL)//初始化棋盘
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
之后用循环将棋盘打印出来
void printboard(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");
}
}
}
之后要实现玩家下棋功能,要注意的点是玩家不能再已经有棋子的格子上下棋。这里玩家棋子使用的是“*”
void playchess(char board[row][col], int ROW, int COL)//玩家下棋
{
int a = 0;
int b = 0;
int i = 0;
for (; i == 0;)
{
scanf("%d", &a);
scanf("%d", &b);
a--;
b--;
if (0 <= a && a < 3 && 0 <= b && b < 3 && board[a][b] == ' ')
{
board[a][b] = '*';
i = 1;
}
else
printf("请输入正确的坐标\n");
}
}
然后我们要设计机器下棋,其实就是一个随机版本的玩家下棋。这里机器棋子使用的是“#”。这里也学习了C语言中的真随机技巧,如果调用随机函数将会得到完全固定的下棋套路。
void autochess(char board[row][col], int ROW, int COL)//机器下棋
{
int a = 0;
int b = 0;
for (;;)
{
a = randNext(0,2);
b = randNext(0, 2);
if (board[a][b] == ' ')
{
board[a][b] = '#';
break;
}
else continue;
}
}
//返回[left, right]的随机数
int randNext(int left, int right)
{
static unsigned int seed = 0;
seed++;
srand((unsigned)time(NULL) + seed * seed);
return rand() % (right - left + 1) + left;
}
之后就是难点判断输赢了,要判断横排,竖排和斜排是否有三连。这里我横排和竖排都是采用的可以推广到更大棋盘的写法,但斜排暂时没发现一个普适性的编写方法,待日后修改。
int result(char board[row][col], int ROW, int COL)//判断输赢
{
int i = 0;
int j = 0;
int count = 0;
for (i = 0; i < row; i++)//玩家横排是否三连
{
for (j = 0; j < col; j++)
{
if (board[i][j] == '*')
count += 1;
else
count = 0;
if (count == 3)
return 1;
}
count = 0;
}
for (j = 0; j < row; j++)//玩家竖排是否三连
{
for (i = 0; i < col; i++)
{
if (board[i][j] == '*')
count += 1;
else
count = 0;
if (count == 3)
return 1;
}
count = 0;
}
for (i = 0; i < row; i++)//机器横排是否三连
{
for (j = 0; j < col; j++)
{
if (board[i][j] == '#')
count += 1;
else
count = 0;
if (count == 3)
return 1;
}
count = 0;
}
for (j = 0; j < row; j++)//机器竖排是否三连
{
for (i = 0; i < col; i++)
{
if (board[i][j] == '#')
count += 1;
else
count = 0;
if (count == 3)
return 1;
}
count = 0;
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')//判断斜排是否三连
return 1;
else if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
return 1;
return 0;//都不符合返回0
}
然后再游戏程序里将这些函数串起来,就完成了井字棋。
void game()//游戏主程序
{
char board[row][col];
//储存数据(二维数组)
initboard(board,row,col);
//初始化棋盘
printboard(board,row,col);
//打印棋盘
int i = 0;
for (i = 0; i <= row * col;)
{
if (i >= 9)//是否下满棋盘
break;
printf("玩家下棋请输入坐标\n");
playchess(board, row, col);
printboard(board, row, col);
i++;
//玩家下棋并再次打印棋盘
if (result(board, row, col) == 1)
{
printf("你赢了\n");
break;
}
//输赢判断
if (i >= 9)//是否下满棋盘
break;
printf("机器下棋\n");
autochess(board, row, col);
printboard(board, row, col);
i++;
//机器下棋
if (result(board, row, col) == 1)
{
printf("你输了\n");
break;
}
//输赢判断
}
if (i >= 9)
{
printf("平局\n");
}
}
最后可以在main函数最后加上一个 system("pause"); 使exe文件打开时能看到最后的结果而不是直接关闭程序。