ボーリングスコア計算プログラムMobster Partyでボーリングスコア計 算のプログラムを作ると言うテーマがありました。当日は、子供が通う幼稚園 の夕涼み会とぶつかってしまい、残念ながら参加できませんでした。 開催日の3日前、会社からの帰りの電車の中、ソースコードだけでも参加させ てやれ、とふと思い立って電車の中で10分間モデリングし、帰宅して速攻1時 間でソースコードを書きました。 テストしていたらバグがいくつか見つかり、30分かけてデバッグしました が10フレーム目のスコア計算を間違うバグの修正が完了せず、腹も減ったので 翌日に持ち越し、15分のデバッグで一応完了させました。 そのときのソースコードをここに掲載します。 電車内でのモデリングの際に、まずスコアの計算方法に着目しました。 (スコア計算のプログラムだから当然ですが) あるフレームまでの合計スコアは以下の式で求めることができます。 あるフレームまでの合計スコア=前のフレームまでの合計スコア +そのフレームで倒したピン数 +ボーナスポイント(*) * ストライクの場合は直後の2投で倒したピン数 スペアの場合は直後の1投で倒したピン数 つまり、「前のフレーム」と「直後のn投」というキーワードをヒントにする と、フレームをリンクリストにするのがよさそうです。 というわけで、モデリングのポイントは Frame クラスをリンクリスト形式に してスコア計算に使った点と、スコアが計算できないところはすべて例外をあ げるようにした点です。 作ったクラスは以下の4つ。
さて、以下、そのソースコードです。 コメントもほどんど書いてないし、 リファクタリングもしていないので読みにくくて申し訳ない。 こんなソースでも欲しいという方は ここをクリックしてダウンロード してください。コンパイル済みの class ファイルも含んでいます。 起動はコマンドプロンプトからです。起動すると「input new point: 」と、 倒したピン数の入力を要求します。 D:\java\bowling> java -cp . Bowling input new point:これに続いて倒したピン数を入力するとコンソールにスコア表を出力し、 次のポイントをたずねます。どうぞ、お試しください。 このような感じで動作します。 Frame.java public class Frame { int point[]; Frame prev; Frame next; protected static String MSG = "point unknown"; public Frame(){ point = new int[2]; point[0] = -1; point[1] = -1; prev = null; next = null; } public void setPrevFrame(Frame f){ prev = f; } public void setNextFrame(Frame f){ next = f; } public void addPoint(int p){ if(p < 0 || p > 10){ throw new RuntimeException("range is 0 to 10"); } if(point[0] < 0){ point[0] = p; }else{ if(point[0] + p > 10){ throw new RuntimeException("range is 0 to " + (10 - point[0])); } point[1] = p; } } public void setPoint(int i, int p){ point[i] = p; } public boolean isFilled(){ if(point[0] == 10){ return true; } return point[1] >= 0; } public int getStrikePoint(){ int p = point[0]; whenMinusThrowException(p); if(p == 10){ if(next == null){ throw new RuntimeException(MSG); } p += next.getFirstPoint(); }else{ whenMinusThrowException(point[1]); p += point[1]; } return p; } public int getFirstPoint(){ whenMinusThrowException(point[0]); return point[0]; } public int getSecondPoint(){ whenMinusThrowException(point[1]); return point[1]; } public int getFramePoint(){ if(!isFilled()){ throw new RuntimeException(MSG); } if(point[0] == 10){ return point[0]; } return point[0] + point[1]; } public int getTotal(){ int total = 0; int fp = getFramePoint(); if(prev != null){ total = fp + prev.getTotal(); }else{ total += fp; } if(next != null){ if(point[0] == 10){ return total + next.getStrikePoint(); } if(fp == 10){ return total + next.getFirstPoint(); } return total; } throw new RuntimeException("Internal Error"); } protected void whenMinusThrowException(int p){ if(p < 0){ throw new RuntimeException(MSG); } } } EndFrame.java public class EndFrame extends Frame { public EndFrame(){ point = new int[3]; point[0] = -1; point[1] = -1; point[2] = -1; } public void setPoint(int i, int p){ point[i] = p; } public void addPoint(int p){ if(p < 0 || p > 10){ throw new RuntimeException("range is 0 to 10"); } if(point[0] < 0){ point[0] = p; return; } if(point[1] < 0){ if(point[0] < 10 && point[0] + p > 10){ throw new RuntimeException(); } point[1] = p; return; } point[2] = p; } public boolean isFilled(){ if(point[1] < 0){ return false; } if(point[0] == 10 && point[2] < 0){ return false; } if(point[0] + point[1] < 10){ return true; } return point[2] >= 0; } public int getStrikePoint(){ whenMinusThrowException(point[0]); whenMinusThrowException(point[1]); return point[0] + point[1]; } public int getFirstPoint(){ whenMinusThrowException(point[0]); return point[0]; } public int getSecondPoint(){ whenMinusThrowException(point[1]); return point[1]; } public int getThirdPoint(){ whenMinusThrowException(point[2]); return point[2]; } public int getFramePoint(){ if(!isFilled()){ throw new RuntimeException(MSG); } int p = point[0] + point[1]; if(point[2] >= 0){ p += point[2]; } return p; } public int getTotal(){ int fp = getFramePoint(); if(prev == null){ return fp; } return fp + prev.getTotal(); } } ScoreTable.java public class ScoreTable { private Frame frames[]; public ScoreTable(){ frames = new Frame[10]; Frame prev = null; for(int i = 0; i < 10; i++){ if(i != 9){ frames[i] = new Frame(); }else{ frames[i] = new EndFrame(); } frames[i].setPrevFrame(prev); if(prev != null){ prev.setNextFrame(frames[i]); } prev = frames[i]; } } public Frame getFrame(int i){ return frames[i]; } public boolean isGameOver(){ return frames[9].isFilled(); } } Bowling.java import java.io.*; public class Bowling { private ScoreTable scoreTable; public static void main(String args[]){ Bowling b = new Bowling(); b.doGame(); } public Bowling(){ scoreTable = new ScoreTable(); } public void doGame(){ int no = 0; while(!scoreTable.isGameOver()){ int p = getNewPoint(); Frame frame = scoreTable.getFrame(no); try{ frame.addPoint(p); }catch(Exception e){ e.printStackTrace(); continue; } if(frame.isFilled()){ no++; } printScoreTable(); } } public void printScoreTable(){ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | | | | | | | | | | | | | | | | | | | | | | // | +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+-+-+-+ // | | | | | | | | | | | // +---+---+---+---+---+---+---+---+---+-----+ System.out.println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"); printUpperRow(); System.out.println("+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+-+-+-+"); printLowerRow(); System.out.println("+---+---+---+---+---+---+---+---+---+-----+"); } private void printUpperRow(){ System.out.print("|"); for(int i = 0; i < 10; i++){ Frame frame = scoreTable.getFrame(i); int p; try{ p = frame.getFirstPoint(); if(p == 10){ if(frame instanceof EndFrame){ System.out.print("x"); }else{ System.out.print(" |x|"); continue; } }else{ System.out.print(p); } }catch(Exception e){ System.out.print(" "); } System.out.print("|"); try{ p = frame.getSecondPoint(); if(frame instanceof EndFrame){ if(p == 10){ System.out.print("x"); }else if(p + frame.getFirstPoint() == 10){ System.out.print("/"); }else{ System.out.print(p); } }else{ if(frame.getFramePoint() == 10){ System.out.print("/"); }else{ System.out.print(p); } } }catch(Exception e){ System.out.print(" "); } System.out.print("|"); if(frame instanceof EndFrame){ try{ p = ((EndFrame)frame).getThirdPoint(); if(p == 10){ System.out.print("x"); }else{ System.out.print(p); } }catch(Exception e){ System.out.print(" "); } System.out.print("|"); } } System.out.println(); } private void printLowerRow(){ System.out.print("|"); for(int i = 0; i < 10; i++){ Frame frame = scoreTable.getFrame(i); if(frame instanceof EndFrame){ try{ int total = frame.getTotal(); if(total < 10){ System.out.print(" " + total); }else if(total < 100){ System.out.print(" " + total); }else{ System.out.print(" " + total); } }catch(Exception e){ System.out.print(" "); } }else{ try{ int total = frame.getTotal(); if(total < 10){ System.out.print(" " + total); }else if(total < 100){ System.out.print(" " + total); }else{ System.out.print(total); } }catch(Exception e){ System.out.print(" "); } } System.out.print("|"); } System.out.println(); } public int getNewPoint(){ int p = 0; try{ System.out.print("input new point: "); System.out.flush(); BufferedReader r = new BufferedReader(new InputStreamReader(System.in)); String s = r.readLine(); p = Integer.parseInt(s); }catch(Exception e){} return p; } } |
![]() ![]() ![]() ![]() ![]() ![]() ![]() |
HOME | お勧め書籍 / Profile / リンク |