1. 程式人生 > >C語言實現三子棋遊戲(意義版)

C語言實現三子棋遊戲(意義版)

我還會再遇到ta。

所以,這並不算是真正意義上得離別。

雖然從近幾個月幾乎每天都跟ta走的頗近。每次得相遇都會讓我恍惚。

我想躲著ta的一些,但是每次提起思緒卻總會跟ta不期而遇。

遇時苦惱,別時著迷。

昨日又與ta相遇,這一聚,就是六個多時辰。從正午窗外得鳴笛到回頭時到卷閘門刺耳的伸展,我才想起跟一碗炸醬麵不見不散得約定。

跟後者比起來,離別帶給我的,更是精神食糧。

好了ta就是BUG

實現了三子棋後,這一離別才顯得更有意義。理解和實現差之千里,程式設計就是這樣。對於實現入門三子棋可能是大同小異的,但是我在內部加入了標籤,讓這個小程式變得更加意義深刻,同時一記與BUG的不解之緣。

實現:

首先應該想到使用函式來使分工簡潔明確

選單,遊戲功能。

選單:    

main函式中設定menu()函式來列印選單 即 開始遊戲和退出遊戲,使用do while語句來呼叫遊戲功能game()函式。實現完整的互動。

對於遊戲內部功能game()而言,設定 

1 初始化棋盤 (空格和外觀)列印棋盤 (每次下棋後進行結果顯示)3 使用者下棋   4  電腦隨機下棋 

輸贏判斷 6 平局判斷

這麼多函式都放在一個原始檔顯然是酸辣的,所以我們定義一個實現遊戲的標頭檔案”threechess.h“進行函式的宣告,後編寫定義他們的原始檔”threechess.c".

第一步:先在main函式中講函式流程實現

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include"threechess.h"
#include<Windows.h>
#include<time.h>
void menu()
{
	printf("*******************************************\n");
	printf("------ 我可以大口吞下玻璃而不傷身體--------\n");  //label 1. original test.
	printf("------1.  開始遊戲-------------------------\n");
	printf("------0.  退出遊戲-------------------------\n");
	printf("*******************************************\n");

};void game();
int main()
{
	menu();
	int a = 0;

	do
	{
		assert(scanf("%d", &a));//防止使用者輸入非整型十進位制數字
		switch (a)
		{
		case 1:
			game();
			menu();
			break;
		case 0:
			return 0;
                default: printf("輸入錯誤");
		}
	} while (a);
}

threechess.h

第二步 編寫遊戲功能的標頭檔案

#pragma once
#define ROW 3
#define COL 3


voidinitboard(char arr[ROW][COL], int row, int col);//初始化棋盤
//列印棋盤
void    display(char arr[ROW][COL], int row, int col);
//人走棋
void playermove(char arr[ROW][COL], int row, int col);
//機器走
void automove(char arr[ROW][COL], int row, int col);
//判斷輸贏
int JUDGE(char arr[ROW][COL], int row, int col);
//平局情況
int FULL(char arr[ROW][COL], int row, int col);
threechess.c

第三步在該原始檔中定義功能

#include "threechess.h"
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

void initboard(char arr[ROW][COL], int row, int col)//此處第一個引數是指產生二維指標,不能夠省略第一個下標符第二個下標符和值
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			arr[i][j] = ' ';  //將內容初始化
		}
	}
}
void display(char arr[ROW][COL], int row, int col)//顯示棋盤
{
	int i = 0;
	int j = 0;
	printf("-------------\n");
	for (i = 0; i < row; i++)
	{
		printf("|");
		for (j = 0; j < col; j++)
		{
			printf(" %-2c|", arr[i][j]);
		}
		if (row - 2 == i)
		{
			(printf("        ***幫幫烏干達得可憐兒童!***"));    // label 2.VIM version 
		}
		printf("\n-------------\n");// 目的在於每行列印完了以後再下面加上柵;
	}
}
void playermove(char arr[ROW][COL], int row, int  col) //玩家移動
{
	while (1)
	{
		int x = 0, y = 0;
		assert(scanf("%d%d", &x, &y));//此處強調,如果用使用者輸入的值非十進位制整型,比如%……&*&*!@#asdvc字元型,那麼scanf函式將不進行匹配,返回匹配成功的專案數,用assert斷言函式來進行判斷
		x--;//因為使用者輸入得值位陣列下表加一所以在這裡--
		y--;
		if ((x >= 0 && x < row) && (y >= 0 && y < col))//防止越界
		{
			if (' ' == arr[x][y])
			{
				arr[x][y] = '*';
				break;
			}
			else
			{
				printf("\n此位置已放置\n");
			}
		}
		else
		{
			printf("\n你飄了\n");  //沒放好就是飄了
		}
	}
}

void automove(char arr[ROW][COL], int row, int col)//電腦移動
{
	srand((unsigned)time(NULL));  //設定隨機起點

	while (1)
	{
		int x = rand() % 3;   //使隨機值在0-2
		int y = rand() % 3;
		if (' ' == arr[x][y])  //防止重疊
		{
			arr[x][y] = 'X';
			break;
		}
	}
}
int JUDGE(char arr[ROW][COL], int row, int col)  //判斷
{
	int i = 0;
	for (i = 0; i < ROW; i++)//判斷列
	{
		if (arr[i][COL - 1] == arr[i][COL - 2] && arr[i][COL - 2] == arr[i][COL - 3]) //此處當下標時 數值要-1 很關鍵!
		{
			if (arr[i][COL - 1] != ' ')
			{
				return arr[i][COL - 1];
			}
		}
	}
	for (i = 0; i < COL; i++) //判斷行
	{
		if (arr[ROW - 1][i] == arr[ROW - 2][i] && arr[ROW - 2][i] == arr[ROW - 3][i])
		{
			if (arr[ROW - 1][i] != ' ')
			{
				return arr[ROW - 1][i];
			}
		}
	}
	if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2])  //判斷斜行
	{
		if (arr[0][0] != ' ')
		{
			return arr[0][0];    //返回複合條件的字元
		}
	}
	if (arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0])//判斷對稱斜行
	{
		if (arr[0][2] != ' ')
		{
			return arr[0][2];  //返回複合條件的字元
		}
	}
	if (FULL(arr, row, col) == 0) //在judge中引用FULL函式進行平局判斷
	{
		return 'd';//返回複合條件的字元

	}

	return 0;  //沒有返回0
}
int FULL(char arr[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < ROW; i++)
	{
		for (j = 0; j < COL; j++)
		{
			if (' ' == arr[i][j])
			{
				return 1; //供judge判斷
			}

		}
	}
	return 0;
}


第四步,game()功能實現

void game()
{
	char arr[ROW][COL] = { 0 };
	initboard(arr, ROW, COL);  
	display(arr, ROW, COL);
	
	
		while (1)
		{
			playermove(arr, ROW, COL);  //玩家操作
			display(arr, ROW, COL);//將結果顯示
			if (JUDGE(arr, ROW, COL) != 0)//判斷是否產生結果
			{
				break;
			}
			automove(arr, ROW, COL);  //電腦操作
			display(arr, ROW, COL);//顯示結果
			if (JUDGE(arr, ROW, COL) != 0)//判斷
			{
				break;
			}
			
			
		}
		if (JUDGE(arr, ROW, COL) =='d' )//結束後檢測是否複合平局判斷
		{
			printf("你勉強合格");//輸出平局結果
		}
		else if (JUDGE(arr, ROW, COL) == 'X')//電腦勝出結果判斷
		{
			printf("出門左轉上336\n");
		}
		else if (JUDGE(arr, ROW, COL) == '*')//玩家結果判斷
		{
			printf("THAT'S VERY KIND OF YOU!\n");
		}

	return 0;}                                    

輸出結果

1.介面


1.電腦贏


2.玩家贏


**對於label 1與2 

1.來字linux系統經典字型測試

2.來自vim的歡迎語

顯得更有意義。

**關於scanf的返回值,scanf返回的是正確入讀的專案數,即(%d%d%d,&a,&b)它的返回值也是3,但是如果第一個專案未提取成功,那麼即使後面是正確的型別,返回值也是0