制作简易三子棋过程分析
本篇具体谈论思路和过程
代码:三子棋整个vs文件(包含源代码)
笔记:三子棋思路分析笔记(可提供下载本文)
一、文件构成
1. test.c
用于游戏主功能的基本框架,包含菜单,游戏棋盘,玩家操作,电脑操作
#pragma once #include<stdio.h> #include <stdlib.h> #include<time.h> #define ROW 3 #define COL 3 //棋子准备,将棋盘中清空 void pieces(char pan[ROW][COL], int row, int col); //打印棋盘 void print_pan(char pan[ROW][COL], int row, int col); //玩家下棋 void player_move(char pan[ROW][COL], int row, int col); //电脑下棋 void cpt_move(char pan[ROW][COL], int row, int col); //判断胜负 char judge(char pan[ROW][COL], int row, int col);
2. game.c
用于游戏功能的实现,框架中功能是如何具体实现,基本为函数
3. game.h
包含实现 game.h 和 test.c 中语句所需要引用的函数
#pragma once #include<stdio.h> #include<time.h> #define ROW 3 #define COL 3 //棋子准备,将棋盘中清空 void pieces(char pan[ROW][COL], int row, int col); //打印棋盘 void print_pan(char pan[ROW][COL], int row, int col); //玩家下棋 void player_move(char pan[ROW][COL], int row, int col); //电脑下棋 void cpt_move(char pan[ROW][COL], int row, int col); //判断胜负 char judge(char pan[ROW][COL], int row, int col);
二、实现步骤分析
1. 菜单栏
想要开始游戏必须有 游戏菜单
游戏菜单包含:开始游戏;退出游戏;
实现此过程用switch语句,输入1开始游戏,输入0退出游戏
void menu() { printf("__________1.play__________\n"); printf("__________0.exit__________\n"); }
因为希望游戏是可以重复玩的
所以整个游戏必当在一个循环里面
因此选择 do while 循环语句包含整个功能
int main()
{
int input = 0;//用来接受玩家的命令0/1
do
{
menu();//游戏菜单
scanf("%d", &input);
switch (input)
{
case 1://开始游戏
game();
break;
case 0://结束游戏
break;
default:
printf("请重新输入正确数字\n");
break;
}
} while (input != 0);
}
2. 准备棋子
初步展现的应该是一个空棋盘
而棋盘中的变数是棋盘中的棋子
这些子由玩家或者电脑下
先将玩家和电脑的棋子准备好,在棋盘中显示是空格是即将下的棋子
//准备好棋盘上棋子的位置 void pieces(char pan[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { pan[i][j] = ' '; } } }
这样打印空棋盘的时候直接打印数组就可以了
3. 空棋盘
棋子准备好了,玩家也准备玩了
首先呈现给玩家的是一个空棋盘
将第一、二两行看成一组,一共3组
最后一组和每行的后面需要if语句来改变
test.c代码:
//打印棋盘 void print_pan(char pan[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { printf(" "); printf("%c", pan[i][j]); if (j == (row - 1)) { printf("\n"); break; } printf(" |"); } if (i == (row - 1)) { break; } for (j = 0; j < col; j++) { if (j == (col - 1)) { printf("---\n"); break; } printf("---|"); } } printf("--------------------\n");//分割线 }
效果:
4. 玩家下棋
需要两个参数代表行和列
但真实的行和列和数组里的行列差1
考虑要素
该坐标是否在棋盘内
该坐标是否已经占用
game.c代码:
//玩家下棋 void player_move(char pan[ROW][COL], int row, int col) { printf("请输入您要下棋的位置:");//玩家下棋 int x = 0;//行 int y = 0;//列 scanf("%d%d", &x, &y);//获取行和列 while(1) { if ((x - 1) > row || (x - 1) < 0 || (y - 1) > col || (y - 1) < 0)//不在范围内 { printf("该坐标超出棋盘范围,请重新输入:"); scanf("%d%d", &x, &y); } else//在坐标范围内 { while(pan[x - 1][y - 1] != ' ')//坐标被占用 { printf("该坐标已经占用,请重新输入坐标:"); scanf("%d%d", &x, &y); } //坐标没被占用 pan[x - 1][y - 1] = '#'; break; } } printf("玩家下棋:\n"); }
效果:
5. 电脑下棋
由于电脑是自动下棋,首先来看最简单的随机下棋
考虑因素:
生成随机数(包括行和列):通过%控制数字大小,此处不用判断超出棋盘
随机数函数为rand()
需要头文件<time.h>
判断位置有没有棋子
game.c代码:
//电脑下棋 void cpt_move(char pan[ROW][COL], int row, int col) { srand((unsigned)time(NULL));//先用srand生成随机数 int x = rand() % row; int y = rand() % col; while (1) { if(pan[x][y] == ' ')//坐标没被占用 { pan[x][y] = '*'; printf("电脑下棋:\n"); break; } else//坐标被占用 { x = rand() % row; y = rand() % col;//重新输入数字 } } }
效果:
6. 判断胜负
玩家下棋 打印棋盘 判断胜负 电脑下棋 打印棋盘 判断胜负
整个游戏在重复这个过程
所以应当放在一个do while 循环中
其中最重要的是判断胜负的函数
判断胜负函数
考虑因素:
一行/列或者对角线为同一个元素且该元素不为空格
退出循环 宣布胜利方
如果平局,即在棋盘中没有空格
还没下完,即还需要继续对战
game.c代码:
//判断胜负 玩家胜利返回# 电脑胜利返回* 平局返回 q 未下完返回 c char judge(char pan[ROW][COL], int row, int col) { int i = 0; int j = 0; for(i = 0; i < row; i++)//行 { if ((pan[i][0] == pan[i][1]) && (pan[i][1] == pan[i][2]) && pan[i][0] != ' ') { return pan[i][0]; } } for (j = 0; j < col; j++)//列 { if ((pan[0][j] == pan[1][j]) && (pan[0][j] == pan[2][j]) && pan[0][j] != ' ') { return pan[0][j]; } } //对角线 if ((pan[0][0] == pan[1][1]) && (pan[1][1] == pan[2][2]) && pan[1][1] != ' ') { return pan[1][1]; } if ((pan[0][2] == pan[1][1]) && (pan[1][1] == pan[2][0]) && pan[1][1] != ' ') { return pan[1][1]; } for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { if (pan[i][j] == ' ') { return 'c'; } } } return 'q'; }
效果:
三、test.c文件
进入循环1-打印菜单-获取数字-准备空棋子-打印空棋盘-进入循环2-玩家下棋-判断胜负-电脑下棋-判断胜负-退出循环1-退出循环2
代码:
#define _CRT_SECURE_NO_WARNINGS #include "game.h" void menu() { printf("--> 1.play\n"); printf("--> 0.exit\n"); printf("请输入您的选择:"); } void game() { char broad[ROW][COL] = { 0 }; pieces(broad, ROW, COL);//棋子准备 print_pan(broad, ROW, COL);//打印棋盘 while(1) { player_move(broad, ROW, COL);//玩家下棋 print_pan(broad, ROW, COL);//打印玩家下的棋子 if (judge(broad, ROW, COL) != 'c')//是否继续游戏 { break; } cpt_move(broad, ROW, COL);//电脑下棋 print_pan(broad, ROW, COL);//打印电脑下的棋子 if (judge(broad, ROW, COL) != 'c')//是否继续游戏 { break; } } int ret = judge(broad, ROW, COL); if (ret == '#') { printf("恭喜你胜利了\n"); } else if (ret == '*') { printf("很遗憾你输了\n"); } else { printf("平局\n"); } } int main() { int input = 0; do { menu(); scanf("%d", &input); printf("--------------------\n");//分割线 switch (input) { case 1: game(); break; case 0: break; default: printf("请重新输入正确数字\n"); break; } printf("--------------------\n");//分割线 printf("请选择是否重新开始游戏:\n"); } while (input != 0); }
——————————游戏结束———————————