一、浅谈思路和效果
首先想通过一个简单的菜单,通过输入序号进入游戏。
在输入序号后,显示一个自定义大小的棋盘,用户通过输入序号位置,下好后电脑下,若谁先三点一线则获胜。
- 通过循环和switch实现菜单。
- 每个可下的位置通过数组定义为空,输入位置后通过数组改变值。
- 棋盘通过循环打印
- 电脑的输入通过随机值确认数组下标改变值。
- 最后通过三子棋简单规律实现判断输赢。
二、代码与解释
1.测试页和头文件
首先做项目养成划分测试页、头文件、函数实现页的习惯。
在测试页中,通过简单的循环和switch作为菜单功能的基础。
下面主要实现menu和play 函数。
//建立在源文件Test.c中
#include"game.h"
void Test() {
int input = 0;
do {
menu();//菜单显示函数
printf("请输入:");
scanf("%d", &input);
switch (input) {
case 1:
play();//进入游戏功能的函数
break;
case 0:
printf("退出\n");
break;
default:
printf("输入错误,请重新输入:");
scanf("%d", &input);
}
} while (input);//非0继续循环
}
int main() {
Test();
return 0;
}
//以下放在game.h中,并且在其他函数中需要包含.
#include<stdio.h>
#define ROWS 4//自定义棋盘行数
#define COLS 4//自定义棋盘列数
//以下是需要实现的函数.
//菜单
void menu();
//游玩
void play();
//初始化棋盘数组
void InitBoard(char board[ROWS][COLS]);
//打印棋盘
void ShowBoard(char board[ROWS][COLS]);
//玩家回合的实现
void PlayBoard(char board[ROWS][COLS]);
//电脑回合的实现
void CompBoard(char board[ROWS][COLS]);
//判断输赢
char WinBoard(char board[ROWS][COLS]);
//判断是否平局
char fboard(char board[ROWS][COLS]);
2.功能实现
(1)菜单和游玩功能
菜单很简单
//game.c
//可随意绘制
void menu() {
printf("======================\n");
printf("= 1.play =\n");
printf("= 0.exit =\n");
printf("======================\n");
}
游玩功能
除菜单所有的其他功能都在此调用,可先看其他功能再回来看。
//game.c
//'C'代表继续
void play() {
char board[ROWS][COLS] = { 0 };
srand((unsigned int)time(NULL));
InitBoard(board);
ShowBoard(board);
//循环回合下棋,默认玩家先下
while (1) {
PlayBoard(board, ROWS, COLS);
char ret = WinBoard(board);
if (ret != 'C') {
break;
}
CompBoard(board);
ret = WinBoard(board);
if (ret != 'C') {
break;
}
}
//不为C,不继续就结束判断打印。
char ret = WinBoard(board);
if (ret == '*') {
printf("玩家胜!\n");
}
else if (ret == '#') {
printf("电脑胜利!\n");
}
else{
printf("平局!\n");
}
}
(2)初始化棋盘和打印棋盘功能
在开始为了方便,所有未赋值的定义为空,所以也用字符表示。
//game.c
void InitBoard(char board[ROWS][COLS]) {
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
board[i][j] = ' ';
}
}
}
打印棋盘,也是整个过程最直观的功能
假设行和列都是4时
//game.c
void ShowBoard(char board[ROWS][COLS]) {
int i = 0,j=0;
//一行一行的打印
for (i = 0; i < ROWS; i++)
{
//若为3打印 %c | %c | %c
for (j = 0; j < COLS; j++)
{
printf(" %c ", board[i][j]);
if (j < COLS - 1) //每行只要打印COLS-1个"|"
{
printf("|");
}
}
printf("\n");
//若为3打印---|---|---
if (i < ROWS - 1)
{
for (j = 0; j < COLS; j++)
{
printf("---");
if (j < COLS - 1)//每行只要打印COLS-1个"|"
{
printf("|");
}
}
printf("\n");
}//if i<ROWS-1
}//ROWS的for
printf("\n");
}
(3)玩家回合和电脑回合功能
//game.c
void PlayBoard(char board[ROWS][COLS]) {
int x = 0, y = 0;
printf("玩家下:\n");
printf("请输入下的位置:");
while (1) {
scanf("%d %d", &x, &y);
//判断一下输入的位置范围,和输入位置的值是否为空
if (x > 0 && x <= ROWS && y > 0 && y <= COLS && board[x-1][y-1]==' ') {
board[x - 1][y - 1] = '*';
break;
}
printf("输入错误,请重新输入:");
}
ShowBoard(board);//结束直接打印
}
//game.c
void CompBoard(char board[ROWS][COLS]) {
printf("电脑下:\n");
while (1) {
//循环判断随机的位置是否为空,不为空再获取其它随机值。
int x = rand() % ROWS;
int y = rand() % COLS;
if (board[x][y] == ' ') {
board[x][y] = '#';
break;
}
continue;
}
ShowBoard(board);
}
(4)判断是否结束功能
在这里,通过遍历一个个数组的值,
如果 当前的值与行或者列+1和+2的值相等,返回值。
如果 当前的值与行列都+1和+2的值相等,返回值。
否则进入继续还是平局判断
//game.c
//判断输赢
char WinBoard(char board[ROWS][COLS]) {
int i = 0;
for (i = 0; i < ROWS; i++) {
int j = 0;
for (j = 0; j < COLS; j++) {
//不为空字符进入判断
if (board[i][j] != ' ') {
//如果列上连续的三个值相等就返回,注意j+2不能超过列
if (j<COLS-2 && board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2]) {
return board[i][j];
}
//如果行上连续的三个值相等就返回,注意i+2不能超过行
else if (i < ROWS - 2 && board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j]) {
return board[i][j];
}
//如果左斜线上连续的三个值相等就返回,注意i+2,j+2不能超过行,列。
else if (i<ROWS-2 && j<COLS-2 && board[i][j] == board[i + 1][j+1] && board[i + 1][j+1] == board[i + 2][j+2]) {
return board[i][j];
}
//如果右斜线上连续的三个值相等就返回,注意i+2,j+2不能超过行,列。
else if (i>=2 && j>=2 && board[i][j] == board[i - 1][j - 1] && board[i - 1][j - 1] == board[i - 2][j - 2]) {
return board[i][j];
}
}
}
}
return fboard(board);
}
//game.c
char fboard(char board[ROWS][COLS]) {
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
if (board[i][j] == ' ') {//有空就继续
return 'C';
}
}
}
return 'P';//每空就返回了
}
(5)最后展示一下