C语言 -- 三子棋
本篇主要是用二维数组和多个函数来实现三子棋游戏。
让我们先来看看这个编写这个游戏的思路:首先要打印三子棋的棋盘,然后是玩家下棋,电脑下棋,最后判断谁赢了,或者看看是否平局。
我们用一个头文件 game.h ,一个源文件 game.c(主要的代码都在这里面哦!)和一个源文件测试文件 text.c(主要写整个游戏的具体思路)来编写我们的代码。
*首先我们看看头文件(game.h):
#ifndef __GAME_H__
#define __GAME_H__
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3 //行 自己可以改变棋盘的大小
#define COL 3 //列 同上(不能小于三哦)
void init_board(char board[ROW][COL], int row, int col);
void print_board(char board[ROW][COL], int row, int col);
void player_move(char board[ROW][COL], int row, int col);
void computer_board(char board[ROW][COL], int row, int col);
char is_win(char board[ROW][COL], int row, int col);
//以上是后面源文件中需要调用的函数
enum OPTION
{
EXIT,
PLAY
};
//枚举
#endif // ! __GAME_H__
*再来看看测试文件 (test.c):
#include"game.h"
void menu()
{
printf(" 三子棋游戏 \n");
printf("\n");
printf("***********************************\n");
printf("******* 1. play *******\n");
printf("******* 0. exit *******\n");
printf("***********************************\n");
}
void game()
{
int row = 0;
int col = 0;
char ret = '0';
char board[ROW][COL] = { '0' }; //创建一个数组(棋盘)
init_board(board, ROW, COL); //初始化棋盘,使其都是空格。
print_board(board, ROW, COL); //打印棋盘
while (1)
{
player_move(board, ROW, COL); //玩家下棋
print_board(board, ROW, COL);
ret = is_win(board, ROW, COL);
//判断输赢平局
if (ret == 'X')
{
printf("恭喜你,赢了!\n");
break;
}
else if (ret == 'Q')
{
printf("平局\n");
break;
}
computer_board(board, ROW, COL); //电脑下棋
print_board(board, ROW, COL);
ret = is_win(board, ROW, COL);
//判断
if (ret == 'O')
{
printf("电脑赢了!\n");
break;
}
else if (ret == 'Q')
{
printf("平局\n");
break;
}
}
}
int main()
{
int input = 0;
srand((unsigned int)(time(NULL)));
menu(); //打印菜单
do
{
printf("请选择:");
scanf_s("%d", &input);
switch (input)
{
case PLAY:
game();
break;
case EXIT:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择!\n");
break;
}
} while (input);
return 0;
}
*最后来看看最重要的 game.c ,让我们分部来看:
初始化数组,元素都是空格
void init_board(char board[ROW][COL], int row, int col)
{
memset(board, ' ', sizeof(board[0][0]) * row * col);
}
不知道memset函数的点击这里 ==> 点击打开链接
接下来就要打印棋盘了,如下图(3*3棋盘),我们将它分成后面这个图看看。
看红色的(横着看),发现最后一个红框里面比前面的少一个 ‘ | ’;
再看紫色的,发现最后一行比上面少底下一行;
观察完了,我们来实现代码
void print_board(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < col; i++)
{
for (j = 0; j < row; j++)
{
printf(" %c ", board[i][j]);
if (j != row - 1)
{
printf("|");
}
}
printf("\n");
if (i != col - 1)
{
for (j = 0; j < row; j++)
{
printf("---");
if (j != row - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
*玩家下棋
void player_move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
printf("玩家走\n");
printf("请输入你要下棋的坐标:");
scanf_s("%d %d", &x, &y);
if (((x > 0) && (x <= row)) && ((y > 0) && (y <= col))) //下棋的坐标要在棋盘内。
{
if (board[x - 1][y - 1] == ' ') //注:玩家输入的坐标假如是(1 1),写代码的应该知道其实是(0 0)
{
board[x - 1][y - 1] = 'X';
break;
}
else
{
printf("输入的坐标已有棋子,请重新输入!\n");
}
}
else
{
printf("输入棋子的坐标有误,请重新输入!\n");
}
}
}
注:玩家输入的坐标假如是(1 1),写代码的应该知道其实是(0 0)
{
board[x - 1][y - 1] = 'X';
break;
}
else
{
printf("输入的坐标已有棋子,请重新输入!\n");
}
}
else
{
printf("输入棋子的坐标有误,请重新输入!\n");
}
}
}
*电脑下棋
void computer_board(char board[ROW][COL], int row, int col)
{
printf("电脑走\n");
while (1)
{
int x = rand() % row; //srand((unsigned int)(time(NULL))
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = 'O';
break;
}
}
}
*判断输赢还有平局
char is_win(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
for (x = 1; x < row - 1; x++)
{
for (y = 0; y < col; y++)
{
if ((board[x][y] == board[x - 1][y]) && (board[x][y] == board[x + 1][y]) && board[x][y] != ' ')
{
return board[x][y];
}
}
}
for (x = 0; x < row; x++)
{
for (y = 1; y < col - 1; y++)
{
if ((board[x][y] == board[x][y - 1]) && (board[x][y] == board[x][y + 1]) && board[x][y] != ' ')
{
return board[x][y];
}
}
}
for (x = 1; x < row - 1; x++)
{
for (y = 1; y < col - 1; y++)
{
if (((board[x][y] == board[x - 1][y - 1]) && (board[x][y] == board[x + 1][y + 1]) && board[x][y] != ' ')
|| ((board[x][y] == board[x - 1][y + 1]) && (board[x][y] == board[x + 1][y - 1])) && board[x][y] != ' ')
return board[x][y];
}
}
if (is_full(board, ROW, COL) == 1) //判断棋盘是否满了(平局)
{
return 'Q'; //表示棋盘满了
}
}
static int is_full(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
想想上面那段代码可以优化吗?
我们可以把玩家或者电脑下棋的坐标传过来,以这个坐标为中心判断输赢,就不用重新一个一个的找,一个一个判断。(可以自己试试哦!)
最后我们来看看结果(3*3棋盘)
再来看一个(5*5棋盘)
好了,这样这个三子棋代码就完成了!学会了吗?