2

OpenGLでレンダリングされたチェスゲームを作っています。

すべての答えを教えてくれる人を探しているわけではありません。自分でコードを理解したいのですが、正しい概念を教えてくれることが本当に必要です。この時点で、どこから始めればよいかわかりません。これが私が理解したものです:

TurnState次の値を持つ列挙型:

  • playerOneTurn
  • playerTwoTurn
  • Stopped

GameState次の値を持つ列挙型:

  • playerOneCheck
  • playerTwoCheck
  • playerOnecCheckMate
  • PlayerTwoCheckMate
  • InitializingGame
  • Tie
  • NormalPlay

抽象クラスPlayerとサブクラスComputer.

ChessGame次のフィールドを持つクラス:

Player p1, p2
TurnState turnState
GameState gameState 

Move次のフィールドを持つクラス:

*Piece
Location origin
Location destination

Location次のフィールドを持つクラス:

row
col
*ChessBoard 

を受け取り、移動が有効かどうかをチェックChessBoardする 1 つのメソッドを持つクラス。isValidMove

ChessPieces次のメソッドを持つ抽象クラス:

GetValue()      // returns an int value of the piece (for scoring)
GetPosition()   // returns the current position of a piece
getIsSelected() // returns a boolean, true if selected, false if unselected
move()          // moves the piece in a way dependent upon what piece 

そして、以下のサブクラス:

  • Pawn
  • Rook
  • Queen
  • King
  • Knight
4

3 に答える 3

3

チェス ゲームの AI 部分については、次のとおりです。

チェス AI やあらゆる種類のターン ベースのゲーム AI を取得するには、特定のターンでのゲームの「価値」を計算する必要があります (これは重要です) (つまり、各駒に値を割り当て、player1 と player1 の値を合計します)。 player2 を実行してから、score = player1score - player2score を実行すると、負の値はプレーヤー 2 に利益をもたらし、正の値はプレーヤー 1 に利益をもたらします。ゲームの

計算できるようになったら、ボードの特定の構成が与えられた場合に、プレーヤーの可能なすべての動きを計算できるようにする必要があります。

これで、ルート ノードとしてゲームの現在の状態を持つ決定木を構築することができます。ツリーの次の「レベル」は、現在の状態 (など) から到達できるすべての可能な状態を表します。プレイヤー 1 がツリーのレベルで可能な動きを考慮した場合、プレイヤー 2 が次のレベルで可能な動きを考慮することに注意することが重要です。

次に行うことは次のとおりです。

プレーヤー 1 が手を打つと仮定すると、プレーヤー 1 は深さ 5 までツリーを調べます (チェス ゲームの場合、ツリー全体を調べることはありません)。したがって、彼は自分に最適化された動きを選択します。つまり、各レベルで、彼は彼の最良の動きまたはプレーヤー 2 の最良の動きを考慮し (したがって、彼は最悪のシナリオで作業します)、そのため、彼はその動きを動かします。ツリーの次のレベルの最高値ノード。

ノードの値を計算するには、次のようにします。 注: ルート ノードが深さ 0 であることを考慮すると、すべての奇数の深さノードは player1 の maxValue であり、すべての偶数の深さノードは player2 の minValue である必要があります。

定義した最大深度までツリーを展開します。maxDepth のノードについては、ボードの値を計算するだけです (回答の冒頭で述べました)。上位ノードについては、次のようにします。

偶数ノードの値 : すべての子ノード間の minValue 奇数ノードの値 : すべての子ノード間の maxValue

したがって、基本的には回帰を実行して、より深いノードの値に基づいてノードの値を見つけます。

ええと、それが基本的なアイデアです。それから他のものを調査できます。必要に応じて私にPMしてください。私はこの種の検索でいくつかの作業を行いました。効率的なコードのために、ここで最も基本的なアイデアを説明しました多くの最適化手法が必要になります。

それが少し役立ったことを願っています

于 2012-09-12T02:46:30.340 に答える
1

まず、AI と GUI/OpenGL の 2 つを分離します。チェスでは、定義済みのプロトコルで通信する 2 つの異なるプロセスに GUI と AI (コンピューター チェス用語で「エンジン」) を配置するのが普通です。このための最も一般的な 2 つのプロトコルは、UCI と WinBoard です。

チェス エンジンの部分では、基本的に次の 3 つが必要です。

  1. ボード/ポジションの表現
  2. リーフノード評価関数
  3. 検索アルゴリズム

読むことをお勧めします:

  1. チェスプログラミング WIKI
  2. コンピューターチェスの TalkChess フォーラム
  3. Stockfish、Crafty、Fruit などのオープン ソースのコンピューター チェス エンジンを調べます。
于 2012-09-12T12:24:44.950 に答える
0

これはあなたの質問に直接答えているわけではないかもしれませんが (実際、あなたの質問は何ですか?)、適切な概念へのポインタが必要だと述べました。

非常に重要な概念の 1 つは、プログラムの各部分を互いに分離することです。

チェスのようなものについては、チェス ゲームの状態の効率的でエレガントな表現が多数存在します。MVC (モデル、ビュー、コントローラー) のデザイン パターンは、チェス ゲームに非常に適していると言えます。

うまくいけば、これはある程度理にかなっていますが、そうでない場合は、MVC についてもう少し読むことをお勧めします。

モデルには、主にゲームの状態の表現を格納するデータ構造が含まれます。これはチェス盤です。ピースは 64 個のスポットのうちの 1 つにしか配置できず、ピースの種類、数、およびそれぞれの機能に制限があります。モデルは、このようなものを処理する責任があります。また、特定の動きの正当性を判断するためのロジック (つまり、ゲームの特定のインスタンスの状態に必ずしも関係しないゲームのプロパティ) をモデルに与えることも理にかなっています。

ビューは、プレゼンテーションに関連するすべてのコードが配置される場所です。OpenGL のすべてがここで実行され、(たとえば) チェス盤の ASCII 表現をコンソールに出力する「デバッグ」ルーチンも同様です。

コントローラーには、ユーザーとやり取りして入力を処理する関数がいくつかある場合があります。コントローラーは、モデル (「E5 を D3 に移動」: コントローラーの関数が を呼び出す可能性がありますmodel.moveKnight('D3')) とビュー (「栄光の 3D でボードを描画する」: コントローラーは を呼び出すようなことを行う可能性がある)openGLView.draw(model)を操作するコードの一部です。

MVC が達成を支援する主な目標の 1 つは、さまざまなタスクを実行するコード部分の独立性です。AI の変更によってレンダリング アルゴリズムに問題が発生した場合、それはイライラする困難な状況です。経験豊富なプログラマーは、これが起こらないようにするために多大な努力を払います。

この時点で、AI コードが全体像のどこに当てはまるのか疑問に思うかもしれません。まあ、それは本当にあなた次第です。最善の判断をしてください。コントローラの一部である可能性があります。個人的には、AI アルゴリズムを実装するまったく別のコントローラー ( chessAIController) を使用したいと思いますが、すべてをメイン コントローラーに含めることも同様に簡単です。

重要なのは、何らかの論理的な方法で行われている限り、コードを実際にどのように編成するかは問題ではありません。MVC が非常に普及している理由は、これら 3 つのコンポーネントが通常ほとんどのソフトウェアに存在し、通常はそれらを分離することが理にかなっているからです。それらは実際には分離されていないことに注意してください...コントローラーは多くの場合、ビューとモデルの両方を直接操作します。ビューが何も操作できないようにするなどの制限は、コードをクリーンでわかりやすいものに保つのに役立ちます。

プログラミング プロジェクトに構造や組織がない場合、機能を構築するコード内の場所は実際には 1 つしかないため、あらゆることを少しずつ実行する巨大なルーチンを避けることはほぼ不可能です。これが常に生成するのは、複雑に絡み合った大量のスパゲッティ コードであり、どんなに高度な言語であっても、そこからあなたを救うことはできません。これは、他の誰もそれを理解できないため、単純に最悪のコードを作成し、書かれてから2週間後には理解できなくなります。

于 2012-09-12T23:18:33.540 に答える