一. 三子棋简单概述
相信大部分人都玩过五子棋,也知道五子棋的规则与玩法。而今天的三子棋就是简易版的五子棋。
首先,在一张3*3的棋盘上,双方先后落子,谁先形成三个相同且相连的棋,谁就赢得了比赛。可以是一排或者一列三个相同,也可以是两个对角线上的三个棋子相同。如下图所示,绿方获胜。
从上方的简单描述中,我们也可以大体知道,c语言实现这样一个单机版的三子棋是什么样的。接下来我们就整体说一下思路。
二. c 语言实现三子棋的总体思路
- 首先,我们需要一个菜单界面,来提示用户进行游戏或者退出。
- 主函数里分为开始游戏(game()函数)和退出,并且不同的情况调用他们各自的函数来实现功能。
- 在game()函数函数里, 首先需要一个3*3的二维数组当作棋盘,并且需要对棋盘初始化,因为双方没落子之前棋盘是空的,所以我们需要将棋盘的每个位置初始化为空格字符( InitBoard()函数 )。游戏一旦开始,我们需要将初始化后的棋盘显示( ShowBoard()函数 )在用户面前。接下来让用户输入自己所要落子的位置,并且判断该位置是否合法。用户落子之后,需要判断当前棋盘是否已满,或者是否有人已经赢得比赛( Judge()函数 )。同样,在用户落子之后,电脑通过生成随机数来落子。
- 最后,通过循环来依次落子。
三. 采取分文件来实现该项目
如上图所示,就是今天分文件项目的三大部分。下面就每个文件里边的内容以及函数的具体实现一一说明。
1.main.c文件
此文件主要是来实现三子棋的总体框架,调用封装好的各个接口。
#include"Game.h"
int main()
{
int quit = 0;
int select = 0;
while (!quit)
{
menu();
printf("\nPlease enter your choice:");
scanf("%d", &select);
switch (select)
{
case 1:
game();
break;
case 2:
quit = 1;
break;
default:
printf("\nInput Error,please enter your choice again:");
break;
}
}
system("pause");
return 0;
}
#include"Game.h"就是我们声明了各大接口函数,以及宏定义、头文件的声明。quit是用来用户是否要退出游戏的一个标志,用户选择2,则quit置为1,!quit就是0,即条件不成立退出循环。
2.Game.h头文件
此文件声明了各大接口函数,以及宏定义、头文件的声明。
#ifndef _GAME_H_
#define _GAME_H_
#include<stdio.h>
#include<Windows.h>
#include<time.h>
#pragma warning(disable:4996)
#define COL 3
#define ROW 3
#define PLAYER 'X' //用户落子用X字符显示
#define COMPUTER 'O' //电脑落子用O字符显示
#define N '1'
#define F '2'
//菜单函数
void menu();
//游戏函数
void game();
//初始化棋盘的函数
void InitBoard(char board[][ROW], int row, int col);
//打印棋盘的函数
void ShowBoard(char board[][ROW], int row, int col);
//电脑落子函数
void ComputerPlay(char board[][ROW], int row, int col);
//判断棋盘是否满 或者此时是否有人赢得比赛
char Judge(char board[][ROW], int row, int col);
#endif
代码里声明的每个函数的功能我都一一标注过~~~。
2.Game.c文件
大头来了!!
首先说一下game()函数,此函数可是整个游戏的中心,能否快乐下棋,就看此成败!
void game()
{
char result ;
//中随机数种子(为后面电脑随机生成坐标种下随机数种子)
srand((unsigned)time(NULL));
//定义3*3的棋盘
char board[ROW][COL];
//初始化表盘
InitBoard(board, ROW, COL);
//通过循环落子
do{
//给用户显示表盘
ShowBoard(board, ROW, COL);
printf("\n");
printf("请落子:");
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
printf("\n");
//判断落子坐标是否合法
if (x<1 || x>3 || y<1 || y>3)
{
printf("您输入的位置有误,请重新输入!\n");
continue;
}
if (board[x - 1][y - 1] !=' ')
{
printf("该位置已经被占用,请重新输入!\n");
continue;
}
//用户落子(修改棋盘界面,让用户看到下棋的过程)
board[x - 1][y - 1] = PLAYER;
//判断棋盘是否下满或者有人是否赢了
result = Judge(board, ROW, COL);
if (result != 'N')//棋盘满了或者赢了
{
ShowBoard(board, ROW, COL);
printf("\n");
break;
}
//电脑落子
ComputerPlay(board, ROW, COL);
result = Judge(board, ROW, COL);
if (result != 'N')
{
ShowBoard(board, ROW, COL);
printf("\n");
break;
}
} while (1);
if (result == PLAYER)
{
printf("\t恭喜你!,你赢了!\n\n");
}
else if (result == COMPUTER){
printf("\t不好意思,电脑赢了!\n\n");
}
else {
printf("\t玩的不错,平局!\n\n");
}
printf("你玩的不错要不要再来一把!!!~~~~~\n");
}
思路我在第二部分也说了,具体到每行代码的注释已经标注~~
菜单函数menu()
void menu()
{
printf("\n\n");
printf("\t\t#######################################################\n");
printf("\t\t#######################################################\n");
printf("\t\t####### ########\n");
printf("\t\t####### Welcome to three-and-crosses world! ########\n");
printf("\t\t####### ########\n");
printf("\t\t####### ########\n");
printf("\t\t####### 1.PLAY 2.EXIT ########\n");
printf("\t\t####### ########\n");
printf("\t\t#######################################################\n");
printf("\t\t#######################################################\n\n");
}
运行结果:
初始化棋盘函数InitBoard()
也就是将九个位置初始化为空格
void InitBoard(char p[][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
p[i][j] = ' ';
}
}
}
打印棋盘函数 ShowBoard()
void ShowBoard(char board[][ROW], int row, int col)
{
int i = 0;
//printf("%d", row);
printf(" 1 2 3\n");
printf(" ---------------\n");
for (; i < row; i++)
{
printf(" %d |", i + 1);
for (int j = 0; j < col; j++)
{
printf(" %c | ", board[i][j]);
}
printf("\n ---------------\n");
}
}
运行结果:
电脑落子函数ComputerPlay()
//电脑下棋
void ComputerPlay(char board[][ROW], int row, int col)
{
while (1)
{
//产生1-2的随机数
int random_x = rand() % row;
int random_y = rand() % col;
//判断此处是否已落子
if (board[random_x][random_y] == ' ')
{
board[random_x][random_y] = COMPUTER;
break;
}
}
}
判断是此时棋盘是否放满Judge()函数
//判断是此时棋盘是否放满(N-->没满,继续走,F--->满了退出)
char Judge(char board[][ROW], int row, int col)
{
int i = 0;
for (; i < row; i++)
{
//判断每行
if (board[i][1] != ' '&& board[i][1] == board[i][0] && board[i][0] == board[i][2])
{
return board[i][1];
}
//判断每列
if (board[1][i] != ' ' && board[1][i] == board[0][i] && board[0][i] == board[2][i])
{
return board[1][i];
}
}
//判断对角线
if ((board[1][1] != ' ' && board[1][1] == board[0][0] && board[0][0] == board[2][2]) || \
(board[1][1] != ' ' &&board[1][1] == board[2][0] && board[2][0] == board[2][2]))
{
return board[1][1];
}
//棋盘全部下满 返回F ;没满 返回N
if (board[1][1] != ' '&& board[0][0] != ' '&& board[2][2] != ' '&& board[1][2] != ' '&& \
board[0][2] != ' '&& board[1][0] != ' '&&board[2][0] != ' '&&board[2][1] != ' '&&board[0][1] != ' ')
{
return 'F';
}
return 'N';
}
运行结果