ボーリングスコア計算プログラム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 / リンク |