⑴ c語言 象棋 走法 表示
語言象棋走法分三種:進、退、平。
象棋棋盤的九條豎線從左到右排列為:
紅方:一、二、三、四、五、六、七、八、九
黑方:1、2、3、4、5、6、7、8、9
進:如馬二進三,就是馬從第二條豎線向前方(對方的方向)走到第三條豎線上。
退:如車一退一,就是把車向後(自己的方向)走一個格子;車一平二,就是向後走兩個格子。 ——(兵、卒不可退)
平:如炮二平五,就是第二條線的炮走到第五條線上。 ——(馬不可平)
如果兩只馬在同一條線上,那麼可以說成前馬進一、後馬退三......
紅棋與黑棋不同:如果紅棋走炮二平五,黑棋也想走同樣的棋路,就要寫成炮2平5.
⑵ C語言編五子棋(二維數組),很簡單
輸入輸出很簡單的吧,主要是如何判斷棋局結束。當前下子位置,共有八個方向,上對下,左對右,左上對右下,右上對左下。舉上對下的例子,我向上和下兩個方向同時搜索,並計數,當計數到5時,則棋局結束,只有當上下兩個方向都不能繼續搜索時,則停止。
⑶ C語言四皇後問題
//title:4皇後問題的回溯演算法求解
//Demo: 1)回溯演算法實現4皇後問題;2)難點:樹形結構的表達;3)用線性容器表達樹形結構,並實現樹的掃描??降低了樹實現的難度
//author: Liping Chen
//email: [email protected]
//published date: 20125-4-11
#include <iostream>
#include <string.h>
#include <vector>
#include <stdlib.h>
using namespace std;
//定義4皇後棋局的數據結構及方法
typedef struct Queen4 {
int vals[16];
int nQueens;
int parent;
//默認構造函數
Queen4() {
for(int i = 0; i < 16; i++)
vals[i] = 0;
parent = 0;
nQueens = 0;
}
//構造函數1
Queen4(int nvals[16]) {
for(int i = 0; i < 16; i++)
vals[i] = nvals[i];
parent = 0;
nQueens = 0;
}
//找到當前布局中不為0的清鎮位置
int getPosition() {
for(int i = 0; i < 16; i++)
if (vals[i] == 0) {
return i;
}
return -1;
}
//當設置皇豎正輪後位置時,標記水平、垂直和斜線位置掩碼
void setQueen(int pos) {
int row, col;
vals[pos] = 1;
nQueens++;
row = pos / 4;
col = pos % 4;
for(int c = 1; c <= 3; c++) {
//右下
if (row + c < 4 && col + c < 4)
if (vals[(row + c) * 4 + (col + c)] == 0)
vals[(row + c) * 4 + (col + c)] = 2;
//左上
if (row - c >= 0 && col - c >= 0)
if (vals[(row - c) * 4 + (col - c)] == 0)
vals[(row - c) * 4 + (col - c)] = 2;
//左下
if (row + c < 4 && col - c >= 0)
if (vals[(row + c) * 4 + (col - c)] == 0)
vals[(row + c) * 4 + (col - c)] = 2;
//右上
if (row - c >= 0 && col + c >= 0)
if (vals[(row - c) * 4 + (col + c)] == 0)
vals[(row - c) * 4 + (col + c)] = 2;
//右水平
if (col + c < 4)
if (vals[row * 4 + (col + c)] == 0)
vals[row * 4 + (col + c)] = 2;
//左水平
if (col - c >= 0)
if (vals[row * 4 + (col - c)] == 0)
vals[row * 4 + (col - c)] = 2;
//下
if (row + c < 4)
if (vals[(row + c) * 4 + col] == 0)
vals[(row + c) * 4 + col] = 2;
//上
if (row - c >余信= 0)
if (vals[(row - c) * 4 + col] == 0)
vals[(row - c) * 4 + col] = 2;
}
}
//輸出當前棋局
void output(int level) {
int cnt = 0;
char chars[100];
for(int k = 0; k < level; k++)
chars[k] = ' ';
chars[level] = '\0';
cout << chars << "Queen4=" << endl << chars;
for(int i = 0; i < 16; i++) {
cout << vals[i] << " ";
cnt++;
if (cnt % 4 == 0) cout << endl << chars;
}
}
//遞歸調用輸出歷史棋局
void outputHist(vector<Queen4>& tr) {
if (parent)
tr[parent].outputHist(tr);
output(0);
}
//由棋的當前布局產生下一布局
void reproce(vector<Queen4>& tr, int pos) {
int nvals[16];
bool inserted;
//思考:為什麼要使用nvals
for(int i = 0; i < 16; i++)
nvals[i] = vals[i];
for(int i = 0; i < 16; i++) {
if (nvals[i] == 0) {
nvals[i] = 1;
//新結果加入容器
Queen4 q(tr[pos].vals);
q.setQueen(i);
q.parent = pos;
tr.push_back(q);
}
}
}
}Queen4;
//程序主函數
int main() {
Queen4 q0; //調用默認構造函數
vector<Queen4> tr; //向量容器??作用相當於隊列,可以向期中添加新的棋盤布局
int levels[1024] = {0}; //記錄每層的孩子數量??用於分層
tr.push_back(q0); //將初始棋盤加入容器
int oldn = 0, newn = 1, level = 0; //存儲變數
//讓根節點產生新孩子,並把新孩子加入容器
//若不再產生新孩子了,則認為已找到答案
//那麼,最底層的就是答案(需要記錄每層所產生的孩子數)
while(newn != oldn) {
//讓最後的孩子再產生新孩子
for(int i = oldn; i < newn; i++) tr[i].reproce(tr, i);
//更新老孩子和新孩子的數量
oldn = newn;
levels[++level] = newn;
newn = tr.size();
}
oldn = 1;
//輸出4皇後問題共有多少種解法
for(int i = levels[level-1]; i < levels[level]; i++) {
cout << "4皇後放置走法:" << oldn++ << endl;
tr[i].outputHist(tr);
}
return 0;
}
⑷ 求八皇後問題C語言源代碼!急!
/*
* File: queen.c
* Description: 求 8 皇後問題回溯演算法
* Created: 2001/11/12
* Author: Justin Hou [mailto:[email protected]]
*/
#include <stdio.h>
#define DelayTime 20000 /* 顯示棋局時間 */
#define TopX 10 /* 棋盤左上角 x 坐標 */
#define TopY 5 /* 棋盤左上角 y 坐標 */
int N = 8; /* 皇後數量 */
int a[8], b[15], c[15];
/*
* a[col-1] 記錄第 col 列有無皇後, 1 表示有。
* b[row+col-2] 記錄從左上數第 row+col-1 條斜率為 1 的線上有無皇後。
* c[row-col+7] 記錄從右上數第 row-col+8 條斜率為 -1 的線上有無皇後。
*/
int Num = 0;
int row;
void BackTrack (int row)
{
int col; /* 局部變數 */
for (col=1; col<=N; col++)
{
if (a[col-1] + b[row+col-2] + c[row-col+N-1] == 0)
{
a[col-1] = 1; /* 更改數據 */
b[row+col-2] = 1;
c[row-col+N-1] = 1;
gotoxy(col*2 + TopX, row + TopY); /* 畫皇後 */
putch('Q');
if (row < N)
{
BackTrack (row + 1);
}
else
{
Num++; /* 遞歸終點 */
gotoxy(40, 9);
printf("Num: %d ", Num);
delay(DelayTime);
}
a[col-1] = 0; /* 清空數據 */
b[row+col-2] = 0;
c[row-col+N-1] = 0;
gotoxy(col*2 + TopX, row + TopY); /* 清除圖象 */
putch('.');
}/* end if */
}/* end for */
}/* end function BackTrack */
void main()
{
int i, j;
clrscr();
gotoxy(1, 10); /* 要求用戶輸入皇後數量 */
printf("Input the number of queen: ");
while(N <= 0 || N > 14)
{
scanf("%d", &N);
if(N > 14) printf("Two huge number, input again:");
if(N <= 0) printf("Can's smaller than 1, again:");
}
clrscr();
for(i=1; i<=N; i++) /* 畫棋盤(Chessboard) */
{
for(j=1; j<=N; j++)
{
gotoxy(i*2 + TopX, j + TopY);
putch('.');
}
}
BackTrack(1); /* 開始回溯演算法 */
gotoxy(12, 17); /* 顯示最後結果 */
printf ("There are %d kinds of solution.\n", Num);
getch();
}
⑸ 用C語言在linux下編寫一個五子棋程序!
五子棋的核心演算法
五子棋是一種受大眾廣泛喜愛的游戲,其規則簡單,變化多端,非常富有趣味性和消遣性。這里設計和實現了一個人機對下的五子棋程序,採用了博弈樹的方法,應用了剪枝和最大最小樹原理進行搜索發現最好的下子位置。介紹五子棋程序的數據結構、評分規則、勝負判斷方法和搜索演算法過程。
一、相關的數據結構
關於盤面情況的表示,以鏈表形式表示當前盤面的情況,目的是可以允許用戶進行悔棋、回退等操作。
CList StepList;
其中Step結構的表示為:
struct Step
{
int m; //m,n表示兩個坐標值
int n;
char side; //side表示下子方
};
以數組形式保存當前盤面的情況,
目的是為了在顯示當前盤面情況時使用:
char FiveArea[FIVE_MAX_LINE][FIVE_MAX_LINE];
其中FIVE_MAX_LINE表示盤面最大的行數。
同時由於需要在遞歸搜索的過程中考慮時間和空間有效性,只找出就當前情況來說相對比較好的幾個盤面,而不是對所有的可下子的位置都進行搜索,這里用變數CountList來表示當前搜索中可以選擇的所有新的盤面情況對象的集合:
CList CountList;
其中類CBoardSituiton為:
class CBoardSituation
{
CList StepList; //每一步的列表
char FiveArea[FIVE_MAX_LINE][FIVE_MAX_LINE];
struct Step machineStep; //機器所下的那一步
double value; //該種盤面狀態所得到的分數
}
二、評分規則
對於下子的重要性評分,需要從六個位置來考慮當前棋局的情況,分別為:-,¦,/,\,//,\\
實際上需要考慮在這六個位置上某一方所形成的子的布局的情況,對於在還沒有子的地方落子以後的當前局面的評分,主要是為了說明在這個地方下子的重要性程度,設定了一個簡單的規則來表示當前棋面對機器方的分數。
基本的規則如下:
判斷是否能成5, 如果是機器方的話給予100000分,如果是人方的話給予-100000 分;
判斷是否能成活4或者是雙死4或者是死4活3,如果是機器方的話給予10000分,如果是人方的話給予-10000分;
判斷是否已成雙活3,如果是機器方的話給予5000分,如果是人方的話給予-5000 分;
判斷是否成死3活3,如果是機器方的話給予1000分,如果是人方的話給予-1000 分;
判斷是否能成死4,如果是機器方的話給予500分,如果是人方的話給予-500分;
判斷是否能成單活3,如果是機器方的話給予200分,如果是人方的話給予-200分;
判斷是否已成雙活2,如果是機器方的話給予100分,如果是人方的話給予-100分;
判斷是否能成死3,如果是機器方的話給予50分,如果是人方的話給予-50分;
判斷是否能成雙活2,如果是機器方的話給予10分,如果是人方的話給予-10分;
判斷是否能成活2,如果是機器方的話給予5分,如果是人方的話給予-5分;
判斷是否能成死2,如果是機器方的話給予3分,如果是人方的話給予-3分。
實際上對當前的局面按照上面的規則的順序進行比較,如果滿足某一條規則的話,就給該局面打分並保存,然後退出規則的匹配。注意這里的規則是根據一般的下棋規律的一個總結,在實際運行的時候,用戶可以添加規則和對評分機制加以修正。
三、勝負判斷
實際上,是根據當前最後一個落子的情況來判斷勝負的。實際上需要從四個位置判斷,以該子為出發點的水平,豎直和兩條分別為 45度角和135度角的線,目的是看在這四個方向是否最後落子的一方構成連續五個的棋子,如果是的話,就表示該盤棋局已經分出勝負。具體見下面的圖示:
四、搜索演算法實現描述
注意下面的核心的演算法中的變數currentBoardSituation,表示當前機器最新的盤面情況, CountList表示第一層子節點可以選擇的較好的盤面的集合。核心的演算法如下:
void MainDealFunction()
{
value=-MAXINT; //對初始根節點的value賦值
CalSeveralGoodPlace(currentBoardSituation,CountList);
//該函數是根據當前的盤面情況來比較得到比較好的可以考慮的幾個盤面的情況,可以根據實際的得分情況選取分數比較高的幾個盤面,也就是說在第一層節點選擇的時候採用貪婪演算法,直接找出相對分數比較高的幾個形成第一層節點,目的是為了提高搜索速度和防止堆棧溢出。
pos=CountList.GetHeadPosition();
CBoardSituation* pBoard;
for(i=0;ivalue=Search(pBoard,min,value,0);
Value=Select(value,pBoard->value,max);
//取value和pBoard->value中大的賦給根節點
}
for(i=0;ivalue)
//找出那一個得到最高分的盤面
{
currentBoardSituation=pBoard;
PlayerMode=min; //當前下子方改為人
Break;
}
}
其中對於Search函數的表示如下:實際上核心的演算法是一個剪枝過程,其中在這個搜索過程中相關的四個參數為:(1)當前棋局情況;(2)當前的下子方,可以是機器(max)或者是人(min);(3)父節點的值oldValue;(4)當前的搜索深度depth。
double Search(CBoardSituation&
board,int mode,double oldvalue,int depth)
{
CList m_DeepList;
if(deptholdvalue))== TRUE)
{
if(mode==max)
value=select(value,search(successor
Board,min,value,depth+1),max);
else
value=select(value,search(successor
Board,max,value,depth+1),min);
}
return value;
}
else
{
if ( goal(board)<>0)
//這里goal(board)<>0表示已經可以分出勝負
return goal(board);
else
return evlation(board);
}
}
注意這里的goal(board)函數是用來判斷當前盤面是否可以分出勝負,而evlation(board)是對當前的盤面從機器的角度進行打分。
下面是Select函數的介紹,這個函數的主要目的是根據 PlayerMode情況,即是機器還是用戶來返回節點的應有的值。
double Select(double a,double b,int mode)
{
if(a>b && mode==max)¦¦ (a< b && mode==min)
return a;
else
return b;
}
五、小結
在Windows操作系統下,用VC++實現了這個人機對戰的五子棋程序。和國內許多隻是採用規則或者只是採用簡單遞歸而沒有剪枝的那些程序相比,在智力上和時間有效性上都要好於這些程序。同時所討論的方法和設計過程為用戶設計其他的游戲(如象棋和圍棋等)提供了一個參考。
參考資料:http://www.3800hk.com/Article/cxsj/vc/jdsfvc/2005-08-06/Article_33695.html
⑹ 怎樣用C語言編五子棋
任何一種棋類游戲其關鍵是對當前棋局是否有正確的評分,評分越准確則電腦的AI越高。五子棋游戲也是如此,但在打分之前,我們先掃描
整個棋盤,把每個空位從八個方向上的棋型填入數組gStyle(2, 15, 15, 8, 2),其中第一個下標為1時表示黑棋,為2時表示白棋,第二和第三
個下標表示(x,y),第四個下標表示8個方向,最後一個下標為局大世1時表示棋子數,為2時表示空格數,如:
gStyle(1,2,2,1,1)=3表示與坐標(2,2)在第1個方向上相鄰的黑棋棋子數為3
gstyle(1,2,2,1,2)=4表示與坐標(2,2)在第1個方向上的最近的空格數為4
在定義方向時,也應該注意一定的技巧,表示兩個相反的方向的數應該差4,在程序中我是這樣定義的:
Const DIR_UP = 1
Const DIR_UPRIGHT = 2
Const DIR_RIGHT = 3
Const DIR_RIGHTDOWN = 4
Const DIR_DOWN = 5
Const DIR_DOWNLEFT = 6
Const DIR_LEFT = 7
Const DIR_LEFTUP = 8
這樣我們前四個方向可以通過加四得到另一個方向的值。如果你還是不太明白,請看下面的圖:
---------
---------
---oo----
-ox*xx---
---------
---------
圖中的*點從標為(4,4),(打*的位置是空位),則:
gStyle(2,4,4,1,1)=1在(4,4)點相鄰的上方白棋數為1
gStyle(2,4,4,1,2)=2在(4,4)點的上方距上方白棋最近的空格數為2
gStyle(1,4,4,3,1)=2在(4,4)點相鄰的右方黑棋數為2
gStyle(1,4,4,3,2)=1在(4,4)點的右方距右方黑棋最近的空格數為3
...
一旦把所有空點的棋型值填完,我們很容易地得出黑棋水平方向上點(4,4)的價值,由一個沖桐肢1(我把有界的棋稱為沖)和活2(兩邊無界的
棋稱為活)組成的。對於而白棋在垂直方向上點(4,4)的價值是一個活1,而在/方向也是活1所以,只要我們把該點的對於黑棋和白棋的價值算出
來,然後我們就取棋盤上各個空點的這兩個值的和的最大一點作為下棋的點。然而,對各種棋型應該取什麼值呢?我們可以先作如下假設:
Fn 表示先手n個棋子的活棋型,如:F4表示先手活四
Fn'表示先手n個棋子的沖棋型,如:F4'表示先手沖四
Ln 表示後手n個棋子的活棋型,如:L3表示後手活三
Ln'表示後手n個棋子的沖棋型,如:L3'表示後手沖三
.
.
.
根據在一行中的棋型分析,得到如下關系:
L1'<=F1'<L2'<=F2'<=L1<F1<L2<F2<L3'<=F3'<L4'<F4'=F4
從這個關系包含了進攻和防守的關系(當然,這個關系是由我定的,你可以自己定義這些關系)。對這些關系再進一步細化,如在仿鄭一個可下
棋的點,其四個方向上都有活三,也比不上一個沖四,所以我們可以又得到4*F3<L4'這個關系,同樣,我們還可以得到其它的關系,如:4*F2<L3、4*L3<F3...,這些的關系由於你的定法和我的定法制可能不一樣,這樣計算機的AI也就不一樣,最後我們把分值最小的L1'值定為1,則我們就得
到了下面各種棋型的分值,由C語言表示為:
F[2][5]={{0,2,5,50,16000},{0,10,30,750,16000}};
L[2][5]={{0,1,5,50,3750},{0,10,30,150,4000}};
F數組表示先手,第一個下標為0時表示沖型,第二個下標表示棋子數,則F2'對應F[0][2]L數組表示後手,第一個下標為0時表示沖型,第二
個下標表示棋子數,則L2對應F[1][2]Ok,棋型的分值關系確定好了以後,我們把每一個可下點的四個方向的棋型值相加(包括先手和後手的分
值),最後選擇一個最大值,並把這一點作為計算機要下的點就OK了:)。
後話:
1、得到最大值也許不止一個點,但在我的程序中只選擇第一個最大點,當然你可以用於個隨機數來決定
選擇那一個最大值點,也可以對這些最大值點再作進一步的分析。
2、在這個演算法中我只考慮了周圍有棋子的點,而其它點我沒有考慮。
3、可以再更進一步,用這個演算法來預測以後的幾步棋,再選擇預測值最好的一步,這樣電腦的AI就更高了
4、這個演算法沒有考慮黑棋的禁手(雙3、雙四和多於五子的連棋)。因為在平時我下的五子棋是沒有這些
禁手的。
⑺ 小主教問題 求解 用C語言哈~謝謝了
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
char n[3]={'0','0'};/*用於記錄第幾組解*/
int a[8],b[15],c[24],i;
int h[8]={127,177,227,277,327,377,427,477};/*每個皇後的行坐標*/
int l[8]={252,217,182,147,112,77,42,7}; /*每個皇後的列坐啟卜標*/
void *arrow;
void try(int i)
{int j;
for (j=1;j<=8;j++)
if (a[j-1]+b[i+j-2]+c[i-j+7]==3) /*如果第i列第j行為空*/
{a[j-1]=0;b[i+j-2]=0;c[i-j+7]=0;/*占轎旁銷用第i列第j行*/
putimage(h[i-1],l[j-1],arrow,COPY_PUT);/*顯示皇後圖形*/
delay(500);/*延時*/
if(i<8) try(i+1);
else /*輸出一組解*/
{n[1]++;if (n[1]>'9') {n[0]++;n[1]='0';}
bar(260,300,390,340);/*顯示第n組解*/
outtextxy(275,300,n);
delay(3000);
}
a[j-1]=1;b[i+j-2]=1;c[i-j+7]=1;
putimage(h[i-1],l[j-1],arrow,XOR_PUT);/*消去皇後,繼續尋找下一組解*/
delay(500);
}}
int main(void)
{int gdrive=DETECT,gmode,errorcode;
unsigned int size;
initgraph(&gdrive,&gmode,"");
errorcode=graphresult();
if (errorcode!=grOk)
{printf("Graphics error\n");exit(1);}
rectangle(50,5,100,40);
rectangle(60,25,90,33);
/* 畫皇冠 */
line(60,28,90,28);line(60,25,55,15);
line(55,15,68,25);line(68,25,68,10);
line(68,10,75,25);line(75,25,82,10);
line(82,10,82,25);line(82,25,95,15);
line(95,15,90,25);
size=imagesize(52,7,98,38); arrow=malloc(size);
getimage(52,7,98,38,arrow); /* 把皇冠保存閉游到緩沖區 */
clearviewport();
settextstyle(TRIPLEX_FONT, HORIZ_DIR, 4);
setusercharsize(3, 1, 1, 1);
setfillstyle(1,4);
for (i=0;i<=7;i++) a=1;
for (i=0;i<=14;i++) b=1;
for (i=0;i<=23;i++) c=1;
for (i=0;i<=8;i++) line(125,i*35+5,525,i*35+5); /* 畫棋盤 */
for (i=0;i<=8;i++) line(125+i*50,5,125+i*50,285);
try(1); /* 調用遞歸函數 */
delay(3000);
closegraph();
free(arrow);
}
⑻ c語言 n皇後 求高手
八皇後問題各種語言版本:
http://ke..com/view/698719.htm
#include<iostream.h>
const int n = 15 ; //15皇後問題.改動n可變成N皇後問題
const int n_sub = n - 1 ;
int queen[n] ; //N個棋子.N對應每一列,如n=0的棋子只下在0列,1下1....類推
bool row[n] ; //棋局的每一行是否有棋,有則為1,無為0 ;
bool passive[2*n-1] ; //斜率為1的斜線方向上是不是有皇後
bool negative[2*n-1] ; //斜率為負1的斜線方向上是不是有皇後.
//之所以用全局變數,因全局數組元素值自動為0
int main()
{
int cur = 0 ;//游標,當前移動的棋子(哪一列的棋子)
bool flag = false ; //當前棋子位置是否合法
queen[0] = -1 ; //第0列棋子准備,因一開始移動的就是第0列棋子
int count = 0 ; //一共有多少種下法 ;
cout<<"============================Starting============================="<<endl ;
while(cur>=0)
{
while(cur>=0 && queen[cur]<n && !flag) //當還不確定當前位置是否可下
{
queen[cur]++ ;
// cout<<"第"<<cur<<"列棋子開始走在第"<<queen[cur]<<"行"<<endl ;
// cin.get() ;
if(queen[cur] >= n) { //如果當前列已經下完(找不到合法位置)
// cout<<"當前行是非法行,當前列棋子走完,沒有合法位置,回溯上一列棋子"<<endl ;
// cin.get() ;
queen[cur] = -1 ; //當前列棋子置於准備狀態
cur-- ; //回溯到上一列的棋子
if(cur>=0) {
row[queen[cur]] = false ;
passive[queen[cur] + cur] = false ;
negative[n_sub + cur - queen[cur]] = false ;
}
//由於要移下一步,所以回溯棋子原位置所在行應該沒有棋子啦.置row[]為false
//並且棋子對應的斜線的標志位passive[cur]和negative[cur]也應該要設為false ;
}
else {
//先判斷棋子所在行沒有棋子
if(row[queen[cur]] == false) { //當前行沒有棋子
// cout<<"棋子"<<cur<<"所在行沒有其他棋子,正在檢查斜線"<<endl ;
flag = true ; // 暫設為true,或與之前棋子斜交,則再設為false ;
//以下檢查當前棋子是否與之前的棋子斜線相交
if( passive[queen[cur] + cur] == true || negative[n_sub + cur - queen[cur]] == true) {
flag = false ;
// cout<<"出現斜線相交,該位置不合法"<<endl ;
}
else
flag = true ;
if(flag) { //沒有斜交,位置合法
// cout<<"斜線也沒有相交,該位置合法"<<endl ;
if(cur == n-1) //如果是最後一個棋子
{
// cout<<"棋子走完一輪,總走法加1"<<endl ;
count++ ; //總走法加一 ;
}
row[queen[cur]] = true ;// 當前行設為有棋子
passive[queen[cur] + cur] = true ;//當前行正斜率方向有棋子
negative[n_sub + cur - queen[cur]] = true ; //當前行負斜率方向上也有棋子
cur++ ;
if(cur >= n) {
cur-- ;
row[queen[cur]] = false ;
passive[queen[cur] + cur] = false ;
negative[n_sub + cur - queen[cur]] = false ;//原理同回溯
}
flag = false ;
}
}
}//else
}
}
cout<<n<<"皇後問題一共有"<<count<<"種解法"<<endl ;
return 0 ;
}
你自己修改一下吧。
⑼ C語言編制黑白棋游戲:
#include<stdio.h>
#include<string.h>
#include<windows.h>
#include<stdlib.h>
short int chess[12][12];
short int next[8][2]={{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};/*方向數組*/
void print(); /*輸出函數*/
void calculate(); /*數子函數*/
int main()
{
int state; /*狀態變數*/
/*介紹*/
printf(" 黑白棋 ");
printf("1.黑方先行,雙方交替下棋。 2.一步合法的棋步包括:在一個空格新落下一個棋子,並且翻轉對手一個或多個棋子。 3.新落下的棋子與棋盤上已有的同色棋子間,對方被夾住的所有棋子都要翻轉過來。可以是橫著夾,豎著夾,或是斜著夾。夾住的位置上必須全部是對手的棋子,不能有空格。 4.一步棋可以在數個方向上翻棋
,任何被夾住的棋子都必須被翻轉過來,棋手無權選擇不去翻某個棋子。
5.除非至少翻轉了對手的一個棋子,否則就不能落子。如果一方沒有合法棋步,也就是說不管他下到哪裡,都不能至少翻轉對手的一個棋子,那他這一輪只能棄權,而由他的對手繼續落子直到他有合法棋步可下。
6.如果一方至少有一步合法棋步可下,他就必須落子,不得棄權。
7.棋局持續下去,直到棋盤填滿或者雙方都無合法棋步可下。
8.輸入坐標時,分別輸入橫縱坐標,如: 7 2 表示第7行,第2列。
9.在游戲時,若想查看規則,請輸入 0 0 。
10.形勢判斷請輸入 9 9 。
");
printf(" 1=開始 0=退出 ");
scanf("%d",&state);
if(state==0)
return 0;
else if(state==1)
system("cls");
else
{
printf("錯誤!");
return 0;
}
/*初始化*/
memset(chess,0,sizeof(chess));
chess[5][5]=1,chess[4][4]=1,chess[5][4]=2,chess[4][5]=2;
/*開始*/
int i,j,k; /*i用於步數循環*/
int x,y; /*橫縱坐標*/
int nx,ny; /*檎蟻亂桓鱟?/
int white,black;
for(i=5;i<=64;i++)
{
/*黑方的步驟 */
print();
place:
printf("黑方請輸入坐標:");
scanf("%d%d",&x,&y);
if(x==0&&y==0) /*查看規則*/
{
system("cls");
printf("1.黑方先行,雙方交替下棋。 2.一步合法的棋步包括:在一個空格新落下一個棋子,並且翻轉對手一個或多個棋子。 3.新落下的棋子與棋盤上已有的同色棋子間,對方被夾住的所有棋子都要翻轉過來。可以是橫著夾,豎著夾,或是斜著夾。夾住的位置上必須全部是對手的棋子,不能有空格。 4.一步棋可以在數個方向上翻棋,任何被夾住的棋子都必須被翻轉過來,棋手無權選擇不去翻某個棋子。 5.除非至少翻轉了對手的一個棋子,否則就不能落子。如果一方沒有合法棋步,也就是說不管他下到哪裡,都不能至少翻轉對手的一個棋子,那他這一輪只能棄權,而由他的對手繼續落子直到他有合法棋步可下。 6.如果一方至少有一步合法棋步可下,他就必須落子,不得棄權。 7.棋局持續下去,直到棋盤填滿或者雙方都無合法棋步可下。 8.輸入坐標時,分別輸入橫縱坐標,如: 7 2 表示第7行,第2列。 9.在游戲時,若想查看規則,請輸入 0 0 。 10.形勢判斷請輸入 9 9 。 ");
guize:
printf(" 輸入1以繼續 ");
scanf("%d",&state);
if(state==1)
{
system("cls");
goto place;
}
else
{
printf("錯誤 ");
goto guize;
}
}
else if(x==9&&y==9)
{
calculate();
goto place;
}
/*判斷落子是否合法*/
if(chess[x][y]!=0)
{
printf("非法的落子:該點已有棋! ");
goto place;
}
else
{
bool whether=false; /*是否合法:true表示合法*/
for(j=0;j<=7;j++)
{
nx=x;
ny=y;
white=0;
while(1)
{
nx=nx+next[j][0];
ny=ny+next[j][1];
if((chess[nx][ny]==0&&white==0)||(nx>8||nx<1||ny>8||ny<1))
{
break;
}
else if(chess[nx][ny]==2)
{
white++;
}
else if(chess[nx][ny]==1&&white>0)
{
int change=0;
chess[x][y]=1;
whether=true;
nx=x;
ny=y;
while(change<=white)
{
nx=nx+next[j][0];
ny=ny+next[j][1];
chess[nx][ny]=1;
change++;
}
break;
}
}
if(j==7&&whether==false)
{
printf("非法的落子:該子不能翻轉對方棋子! ");
goto place;
}
}
}
system("cls");
print();
Sleep(3000);
/*白方的步驟*/
bool w=false; /*白方是否無棋可走*/
int recordj,recordk; /*記錄*/
for(j=1;j<=8;j++)
{
for(k=1;k<=8;k++)
{
bool whether=false; /*是否合法:true表示合法*/
int num=0,sum=0; /*計數*/
for(int l=0;l<=7;l++)
{
black=0;
nx=j;
ny=k;
while(1)
{
nx=nx+next[l][0];
ny=ny+next[l][1];
if((chess[nx][ny]==0)||(nx>8||nx<1||ny>8||ny<1))
{
break;
}
else if(chess[nx][ny]==1)
{
black++;
}
else if(chess[nx][ny]==2&&black>0)
{
whether=true;
w=true;
break;
}
}
if(whether==true)
{
sum+=black;
}
}
if(sum>num)
{
num=sum;
recordj=j;
recordk=k;
}
}
}
if(w==true)
{
chess[recordj][recordk]=2;
for(int m=0;m<=7;m++)
{
nx=recordj;
ny=recordk;
black=0;
while(1)
{
nx=nx+next[m][0];
ny=ny+next[m][1];
if((chess[nx][ny]==0)||(nx>8||nx<1||ny>8||ny<1))
{
break;
}
else if(chess[nx][ny]==1)
{
black++;
}
else if(chess[nx][ny]==2&&black>0)
{
int change=0;
nx=recordj;
ny=recordk;
while(change<=black)
{
nx=nx+next[m][0];
ny=ny+next[m][1];
chess[nx][ny]=2;
change++;
}
break;
}
}
}
}
else/*白方無棋可走*/
{
printf("白方無棋可走 ");
}
Sleep(1000);
system("cls");
}
return 0;
}
void print()
{
int p,q;
printf(" 1 2 3 4 5 6 7 8 ");
for(p=1;p<=8;p++)
{
printf("%d",p);
for(q=1;q<=8;q++)
{
if(chess[p][q]==1)
printf("●");
else if(chess[p][q]==2)
printf("○");
else
printf(" ");
}
printf(" ");
}
}
void calculate()
{
int pp,qq;
int bla=0,whi=0;
for(pp=1;pp<=8;pp++)
{
for(qq=1;qq<=8;qq++)
{
if(chess[pp][qq]==1)
bla++;
else if(chess[pp][qq]==2)
whi++;
}
}
printf("黑子數:%d 白子數:%d ",bla,whi);
}
⑽ 在C語言中,什麼叫做「面向對象」,什麼叫做「面向過程」
面向過程就是分析出解決問題所需要的步驟,然後用函數把這些步驟一步一步實現,使用的時候一個一個依次調用就可以了。
面向對象是把構成問題事務分解成各個對象,建立對象的目的不是為了完成一個步驟,而是為了描敘某個事物在整個解決問題的步驟中的行為。
例如五子棋,面向過程的設計思路就是首先分析問題的步驟:1、開始游戲,2、黑子先走,3、繪制畫面,4、判斷輸贏,5、輪到白子,6、繪制畫面,7、判斷輸贏,8、返回步驟2,9、輸出最後結果。把上面每個步驟用分別的函數來實現,問題就解決了。
而面向對象的設計則是從另外的思路來解決問題。整個五子棋可以分為 1、黑白雙方,這兩方的行為是一模一樣的,2、棋盤系統,負責繪制畫面,3、規則系統,負責判定諸如犯規、輸贏等。第一類對象(玩家對象)負責接受用戶輸入,並告知第二類對象(棋盤對象)棋子布局的變化,棋盤對象接收到了棋子的i變化就要負責在屏幕上面顯示出這種變化,同時利用第三類對象(規則系統)來對棋局進行判定。
可以明顯地看出,面向對象是以功能來劃分問題,而不是步驟。同樣是繪制棋局,這樣的行為在面向過程的設計中分散在了總多步驟中,很可能出現不同的繪製版本,因為通常設計人員會考慮到實際情況進行各種各樣的簡化。而面向對象的設計中,繪圖只可能在棋盤對象中出現,從而保證了繪圖的統一。
功能上的統一保證了面向對象設計的可擴展性。比如我要加入悔棋的功能,如果要改動面向過程的設計,那麼從輸入到判斷到顯示這一連串的步驟都要改動,甚至步驟之間的循序都要進行大規模調整。如果是面向對象的話,只用改動棋盤對象就行了,棋盤系統保存了黑白雙方的棋譜,簡單回溯就可以了,而顯示和規則判斷則不用顧及,同時整個對對象功能的調用順序都沒有變化,改動只是局部的。