初始文件建立
首先我們建立game.h,game.c,test.c三個文件,如下圖
在game.h文件中我們引用需要使用到的頭文件和定義標識符以及函數(shù)定義,其余兩個文件包含game.h文件即可,即#include"game.h"。
game.h代碼如下:
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
void InitBoard(char board[ROW][COL]);//棋盤初始化
void DisplayBoard(char board[ROW][COL]);//打印棋盤
void PlayerMove(char board[ROW][COL]);//玩家下棋
void ComputerMove(char board[ROW][COL]);//電腦下棋
char IsWin(char board[ROW][COL]);//判斷勝負
其中ROW和COL兩個標識符定義的是棋盤的行和列大小,方便我們在寫函數(shù)和使用是重復使用數(shù)字,有更高的辨識度,表達更清晰。
主函數(shù)文件
代碼如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
printf("*****************************************\n");
printf("******** 1.play 0.exit ********\n");
printf("*****************************************\n");
}
void game()
{
char board[ROW][COL] = { 0 };
InitBoard(board);
DisplayBoard(board);
char ret = 0;
while (1)
{
PlayerMove(board);
DisplayBoard(board);
ret = IsWin(board);
if (ret != 'c')
break;
printf("電腦下:\n");
ComputerMove(board);
DisplayBoard(board);
ret = IsWin(board);
if (ret != 'c')
break;
}
if (ret == 'O')
printf("玩家贏?。?!\n");
else if(ret == 'X')
printf("電腦贏!??!\n");
else
printf("平局\n");
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("請選擇:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("選擇錯誤,重新選擇!\n");
break;
}
} while (input);
return 0;
}
具體思路:
首先我們從主函數(shù)看,建立整形input是為了后面讓玩家選擇游戲選項,然后就是隨機數(shù)的時間種子建立,在后面的電腦下棋會用到,下面主體就是這個do…while循環(huán),首先是menu菜單,這個函數(shù)里包含的就是游戲選項的打印,然后下面的scanf的用處就是為了記錄玩家的游戲選項的輸入,再由switch語句進行語句判定,輸入1進入游戲,輸入0退出游戲,輸入其他則退出游戲,我們再來看game函數(shù),首先建立棋盤(其本質是一個二維數(shù)組),值默認為0,需要注意的是,這里我們下棋時,棋盤內放什么,棋盤類型就定義什么,比如這里我放的是字符,那就使用char類型;再進行初始化,初始化后數(shù)組內均為空格,然后打印棋盤,建立一個字符類型ret,用于接收判斷勝負的信息,然后就是關于人機下棋的一個循環(huán),只要沒有勝負結果跳出,就一直循環(huán);然后就是玩家下棋,再打印,此時有一個判斷,這里的’c’再判斷勝負函數(shù)中是繼續(xù)的信息,也就是說,如果不滿足繼續(xù)下的條件,就跳出,電腦下同理,最后一段就是勝負的判定,如果接收的返回值是’O’,那么玩家勝利,如果接收的返回值是’X’,那么電腦勝利,否則就是平局,具體實現(xiàn)看下面的函數(shù)搭建
棋盤的初始化(InitBoard)
從這里開始,下面所有的函數(shù)都是包含在game.c文件中的
代碼如下:
void InitBoard(char board[ROW][COL])
{
int i = 0;
for (i = 0; i < ROW; i++)
{
int j = 0;
for (j = 0; j < COL; j++)
{
board[i][j] = ' ';
}
}
}
具體思路:
這里就是利用兩個循環(huán)將棋盤中所有元素初始化為空格
打印棋盤(DisplayBoard)
代碼如下:
void DisplayBoard(char board[ROW][COL])
{
int i = 0;
for (i = 0; i < ROW; i++)
{
int j = 0;
for (j = 0; j < COL; j++)
{
printf(" %c ", board[i][j]);
if (j < ROW - 1)
printf("|");
}
printf("\n");
if(i < ROW - 1)
{
for (j = 0; j < COL; j++)
{
printf("---");
if (j < COL - 1)
printf("|");
}
printf("\n");
}
}
}
具體思路:
首先我們看下面這個圖,即為要打印棋盤的效果
我們把棋盤分為兩種類型,按行打印,上面這種寫法可以在需要時改變棋盤大小,而不再需要改變函數(shù),首先我們看第一行包含空格棋子空格豎杠,總共是3個,最后一個沒有豎杠,由此第一行類型的打印循環(huán)就寫出來了,再看第二行包含三個橫杠加一個豎杠,最后一個不加,還需要注意的是,最后一行不打印這個,因此第二行類型打印循環(huán)也寫出,整個打印循環(huán)原理就是這樣
玩家下棋(PlayerMove)
代碼如下:
void PlayerMove(char board[ROW][COL])
{
int x = 0, y = 0;
printf("玩家下棋:>\n");
while (1)
{
printf("請輸入下棋坐標,中間用空格隔開:>");
scanf("%d%d", &x, &y);
if(x>=1&&x<=3&&y>=1&&y<=3)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = 'O';
break;
}
else
printf("此處被占用,請重新落子\n");
}
else
{
printf("坐標非法,請重新落子\n");
}
}
}
具體思路:
首先我們創(chuàng)建xy兩個變量用于接收玩家要落子的坐標,這里的while循環(huán)是為了防止玩家輸錯坐標而建立的,如果輸入正確就會跳出循環(huán),這里的判定條件是以行列為1-3的標準,所以在二維數(shù)組中還要減去1才能找到正確位置,下面的判定條件是為空才能落子,被占用或者輸入非法坐標都會重新進入循環(huán)再輸入坐標。玩家落子為字母O。
如圖:
電腦下棋(ComputerMove)
代碼如下:
void ComputerMove(char board[ROW][COL])
{
while (1)
{
int x = rand()%ROW, y = rand()%COL;
if (board[x][y] == ' ')
{
board[x][y] = 'X';
break;
}
}
}
具體思路:
這里就用到了這個以時間為種子的隨機數(shù),將它模上行和列,得到的即為0-2的隨機值,判定條件也是不為空就落子。電腦落子為字母X。
如圖:
判定勝負
代碼如下:
char IsWin(char board[ROW][COL])
{
int i = 0;
for (i = 0; i < ROW; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')//行
{
return board[i][0];
}
}
for (i = 0; i < COL; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')//列
{
return board[0][i];
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')//對邊
return board[0][0];
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')//對邊
return board[0][2];
if (IsFull(board) == 1)
return 'q';
return 'c';
}
具體思路:
三子棋的勝負只有三種情況,就是同行相同、同列相同、對角相同,根據(jù)這幾種情況寫出判定想等且不為空的條件語句,然后返回任意一個條件中任意一個元素即可。最后判定是不是滿了,如果棋盤滿了返回任意值都可(不等于’c’就行,'c’是繼續(xù)的條件),最后上面的條件都不滿足,則繼續(xù)。
這里還有一個判定棋盤是否滿了的函數(shù)
代碼如下:
int IsFull(char board[ROW][COL])
{
int i = 0,j = 0;
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
就是對二維數(shù)組的遍歷匹配,如果有空位置,則返回0,都不符合,則返回1。
勝負判定如圖:
平局
玩家贏
電腦贏
因為隨機數(shù)的原因,其實要贏很簡單,但是要輸很難,所以這段代碼實現(xiàn)游戲的最終目的是讓電腦贏(手動滑稽)
所有代碼
game.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
void InitBoard(char board[ROW][COL]);
void DisplayBoard(char board[ROW][COL]);
void PlayerMove(char board[ROW][COL]);
void ComputerMove(char board[ROW][COL]);
char IsWin(char board[ROW][COL]);
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void InitBoard(char board[ROW][COL])
{
int i = 0;
for (i = 0; i < ROW; i++)
{
int j = 0;
for (j = 0; j < COL; j++)
{
board[i][j] = ' ';
}
}
}
void DisplayBoard(char board[ROW][COL])
{
int i = 0;
for (i = 0; i < ROW; i++)
{
int j = 0;
for (j = 0; j < COL; j++)
{
printf(" %c ", board[i][j]);
if (j < ROW - 1)
printf("|");
}
printf("\n");
if(i < ROW - 1)
{
for (j = 0; j < COL; j++)
{
printf("---");
if (j < COL - 1)
printf("|");
}
printf("\n");
}
}
}
void PlayerMove(char board[ROW][COL])
{
int x = 0, y = 0;
printf("玩家下棋:>\n");
while (1)
{
printf("請輸入下棋坐標,中間用空格隔開:>");
scanf("%d%d", &x, &y);
if(x>=1&&x<=3&&y>=1&&y<=3)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = 'O';
break;
}
else
printf("此處被占用,請重新落子\n");
}
else
{
printf("坐標非法,請重新落子\n");
}
}
}
void ComputerMove(char board[ROW][COL])
{
while (1)
{
int x = rand()%ROW, y = rand()%COL;
if (board[x][y] == ' ')
{
board[x][y] = 'X';
break;
}
}
}
int IsFull(char board[ROW][COL])
{
int i = 0,j = 0;
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
char IsWin(char board[ROW][COL])
{
int i = 0;
for (i = 0; i < ROW; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
{
return board[i][0];
}
}
for (i = 0; i < COL; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
{
return board[0][i];
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
return board[0][0];
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
return board[0][2];
if (IsFull(board) == 1)
return 'q';
return 'c';
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
printf("*****************************************\n");
printf("******** 1.play 0.exit ********\n");
printf("*****************************************\n");
}
void game()
{
char board[ROW][COL] = { 0 };
InitBoard(board);
DisplayBoard(board);
char ret = 0;
while (1)
{
PlayerMove(board);
DisplayBoard(board);
ret = IsWin(board);
if (ret != 'c')
break;
printf("電腦下:\n");
ComputerMove(board);
DisplayBoard(board);
ret = IsWin(board);
if (ret != 'c')
break;
}
if (ret == 'O')
printf("玩家贏?。。n");
else if(ret == 'X')
printf("電腦贏?。。n");
else
printf("平局\n");
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("請選擇:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("選擇錯誤,重新選擇!\n");
break;
}
} while (input);
return 0;
}
結語
近期更新大量C語言的博客,希望大家多支持!??!文章來源:http://www.zghlxwxcb.cn/news/detail-436474.html
有興趣的小伙伴可以關注作者,如果覺得內容不錯,請給個一鍵三連吧,蟹蟹你喲!??!
制作不易,如有不正之處敬請指出
感謝大家的來訪,UU們的觀看是我堅持下去的動力
在時間的催化劑下,讓我們彼此都成為更優(yōu)秀的人吧?。?!文章來源地址http://www.zghlxwxcb.cn/news/detail-436474.html
到了這里,關于C語言初階之三子棋的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!