我终于开始自己开始,而不是在线跟踪课程,并试图自己创造一些东西,它只是一个简单的基于文本的地牢类型的游戏。
然而,当我将新值从一个类传递到另一个类时,我知道我搞砸了,我尝试将值设置为传递给另一个类的类
package com.company;
import java.util.Random;
import java.util.Scanner;
public class CharBuilder {
static public Random randNum = new Random();
static public Scanner sc = new Scanner(System.in);
private String mCharacterName;
private int mStrength = 6;
private int mIntelligence = 6;
private int mConstitution = 6;
private int mDexterity = 6;
private int mHitPoints = 40;
private int mManaPoints = 40;
private String mCharClass;
private CharBuilder hero;
public CharBuilder(String charClass,int str, int intl, int con, int dex, int hp, int mp) {
mCharClass = charClass;
mStrength = str;
mIntelligence = intl;
mConstitution = con;
mDexterity = dex;
mHitPoints = hp;
mManaPoints = mp;
}
public CharBuilder() {
}
public CharBuilder(String charClass) {
mCharClass = charClass;
}
public void characterNameCreator() {
System.out.println("Greetings, what is your name adventurer? ");
mCharacterName = sc.nextLine();
System.out.printf("I see, so your name is %s very well, very well \n", mCharacterName);
}
public void createHero() {
hero = new CharBuilder(mCharClass,mStrength,mIntelligence,mConstitution,mDexterity,mHitPoints,mManaPoints);
String acceptedAnswers = "warrior wizard thief";
System.out.printf("%s would you say you are more of a warrior, wizard or more of the thievery type \n", mCharacterName);
String classAnswer = sc.nextLine();
boolean isAcceptableClass = classAnswer.contains(acceptedAnswers);
do {
if (classAnswer.equalsIgnoreCase("warrior")) {
mCharClass = "warrior";
hero.setStr(mStrength + 3);
hero.setIntelligence(mIntelligence - 1);
hero.setmConstitution(mConstitution + 4);
hero.setmDexterity(mDexterity + 1);
hero.setHitPoints(mHitPoints + 20);
hero.setManaPoints(mManaPoints - 10);
} else if (classAnswer.equalsIgnoreCase("Wizard")) {
mCharClass = "wizard";
hero.setStr(mStrength -1);
hero.setIntelligence(mIntelligence + 3);
hero.setmConstitution(mConstitution + 2);
hero.setmDexterity(mDexterity);
hero.setHitPoints(mHitPoints - 10);
hero.setManaPoints(mManaPoints + 30);
} else if (classAnswer.equalsIgnoreCase("thief") || classAnswer.equalsIgnoreCase("thievery")) {
mCharClass = "thief";
hero.setStr(mStrength + 2);
hero.setIntelligence(mIntelligence + 1);
hero.setmConstitution(mConstitution + 1);
hero.setmDexterity( mDexterity + 5);
hero.setHitPoints(mHitPoints + 10);
hero.setManaPoints(mManaPoints + 10);
} else {
System.out.println("I'm sorry, that is not an acceptable class, please pick warrior, wizard, or thief");
createHero();
}
}while (isAcceptableClass);
}
public int getStrength() {
return mStrength;
}
public int getIntelligence() {
return mIntelligence;
}
public int getConsitution() {
return mConstitution;
}
public int getDex() {
return mDexterity;
}
public int getHP() {
return mHitPoints;
}
public int getMP() {
return mManaPoints;
}
public CharBuilder getHero() {
return hero;
}
public void setStr(int str) {
mStrength = str;
}
public void setIntelligence(int intl) {
mIntelligence = intl;
}
public void setmConstitution(int con) {
mConstitution = con;
}
public void setmDexterity(int dex) {
mDexterity = dex;
}
public void setHitPoints( int hitPoints) {
mHitPoints = hitPoints;
}
public void setManaPoints( int manaPoints) {
mManaPoints = manaPoints;
}
public void setmCharClass(String charClass) {
mCharClass = charClass;
}
}
和我试图将变量传递给的类似乎没有得到任何东西,因为它给了我一个nullPointerException所以我知道当我要求它时没有任何价值它,我已经把下面的课程包括在内了,
package com.company;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
public class Combat {
Scanner sc = CharBuilder.sc;
Random randNum = CharBuilder.randNum;
List<Enemy> enemyList = new Enemy().createList();
Enemy enemy = enemyList.get(randNum.nextInt(enemyList.size()));
CharBuilder character = new CharBuilder().getHero();
int charStrength = character.getStrength();
int charHp = character.getHP();
int enemyHp = enemy.getHP();
int enemyStr =enemy.getStr();
String enemyName = enemy.getName();
public void initiateCombat() {
System.out.printf("A %s appears, it has %d hitpoints, and it's strength is %s \n", enemyName, enemyHp, enemyStr);
}
public void playersTurn() {
System.out.println("It is your turn, your available actions are attack, or use a skill");
String actionAnswer = sc.nextLine();
if (actionAnswer.equalsIgnoreCase("attack")) {
enemyHp -= charStrength;
System.out.printf("You attack the enemy, doing %s damage, the enemy currently has %s hp left \n", charStrength,
enemyHp);
}
else {
System.out.println("Sorry, please choose attack or skill ");
playersTurn();
}
}
public void enemyTurn() {
charHp -= enemyStr;
System.out.printf("It is the enemy's turn, it attacks doing %s damage, your current hp is %s \n", enemyStr, charHp);
}
public void combat() {
while(enemyHp >= 0 && charHp >= 0) {
initiateCombat();
playersTurn();
if (enemyHp <= 0) {
System.out.println("You have defeated the enemy, congratulations");
break;
}
enemyTurn();
}
}
}
任何关于我做错事的新人的提示,以及我如何能够获得这些价值?我知道我可以宣布英雄是静态的,但有更好的方法吗?
我在第一个可能的区域获得NullPointerException
,他们试图从CharBuilder
类中提取数据。这是
int charStrength = character.getStrength();
答案 0 :(得分:1)
在您的构造函数中调用createHero()
之前,您需要在CharBuilder
上致电getHero()
。
答案 1 :(得分:1)
让我们看看为什么你有NPE
问题:
看看这里
public CharBuilder() {
}
第一个构造函数是默认构造函数。它只初始化最小值,并允许用户使用getter和setter设置其余部分。
CharBuilder character = new CharBuilder().getHero();
some setters is missing here?
int charStrength = character.getStrength();
正如您在代码中看到的那样,您没有在病房后设置任何内容
此外,定义默认构造函数有三个常见原因:
- 使用默认值构建对象。
- 初始化在初始化过程中不需要参数的对象。
- 重新定义构造函数的范围。使构造函数私有将阻止除了类本身之外的任何人构造一个 对象。
醇>
如果要确保创建的任何实例始终有效并且始终初始化任何成员变量,那么您将定义初始化所有必需成员变量的构造函数。
在您的情况下,您可以在createHero
之前使用getHero
功能,因为createHero
会设置值。
<强>建议强>:
Plaese看一下构建器模式来设计更好的类
答案 2 :(得分:1)
你的代码应该是,
/**
* Main function to register all of the plugin settings
*
* @since 1.0.0
*/
function sc_register_settings() {
global $sc_options;
$sc_options = array();
$sc_settings = array(
/* Default Settings */
'default' => array(
'note' => array(
'id' => 'settings_note',
'name' => '',
'desc' => sprintf( '<a href="%s" target="_blank">%s</a>', sc_ga_campaign_url( SC_WEBSITE_BASE_URL . 'docs/shortcodes/stripe-checkout/', 'stripe_checkout', 'settings', 'docs' ), __( 'See shortcode options and examples', 'sc' ) ) . ' ' .
__( 'for', 'sc' ) . ' ' . Stripe_Checkout::get_plugin_title() . '<br/>' .
'<p class="description">' . __( 'Shortcode attributes take precedence and will always override site-wide default settings.', 'sc' ) . '</p>',
'type' => 'section'
),
'name' => array(
'id' => 'name',
'name' => __( 'Site Name', 'sc' ),
'desc' => __( 'The name of your store or website. Defaults to Site Name.' , 'sc' ),
'type' => 'text',
'size' => 'regular-text'
),
'currency' => array(
'id' => 'currency',
'name' => __( 'Currency Code', 'sc' ),
'desc' => __( 'Specify a currency using it\'s ', 'sc' ) .
sprintf( '<a href="%s" target="_blank">%s</a>', 'https://support.stripe.com/questions/which-currencies-does-stripe-support', __( '3-letter ISO Code', 'sc' ) ) . '. ' .
__( 'Defaults to USD.', 'sc' ),
'type' => 'text',
'size' => 'regular-text'
),
'image_url' => array(
'id' => 'image_url',
'name' => __( 'Image URL', 'sc' ),
'desc' => __( 'A URL pointing to a square image of your brand or product. The recommended minimum size is 128x128px.' , 'sc' ),
'type' => 'text',
'size' => 'regular-text'
),
'checkout_button_label' => array(
'id' => 'checkout_button_label',
'name' => __( 'Checkout Button Label', 'sc' ),
'desc' => __( 'The label of the payment button in the checkout form. You can use {{amount}} to display the amount.' , 'sc' ),
'type' => 'text',
'size' => 'regular-text'
),
'payment_button_label' => array(
'id' => 'payment_button_label',
'name' => __( 'Payment Button Label', 'sc' ),
'desc' => __( 'Text to display on the default blue button that users click to initiate a checkout process.' , 'sc' ),
'type' => 'text',
'size' => 'regular-text'
),
'success_redirect_url' => array(
'id' => 'success_redirect_url',
'name' => __( 'Success Redirect URL', 'sc' ),
'desc' => __( 'The URL that the user should be redirected to after a successful payment.' , 'sc' ),
'type' => 'text',
'size' => 'regular-text'
),
'disable_success_message' => array(
'id' => 'disable_success_message',
'name' => __( 'Disable Success Message', 'sc' ),
'desc' => __( 'Disable default success message.', 'sc' ) . '<br/>' .
'<p class="description">' . __( 'Useful if you are redirecting to your own success page.', 'sc' ) . '</p>',
'type' => 'checkbox'
),
'failure_redirect_url' => array(
'id' => 'failure_redirect_url',
'name' => __( 'Failure Redirect URL', 'sc' ),
'desc' => __( 'The URL that the user should be redirected to after a failed payment.' , 'sc' ),
'type' => 'text',
'size' => 'regular-text'
),
'billing' => array(
'id' => 'billing',
'name' => __( 'Enable Billing Address', 'sc' ),
'desc' => __( 'Require the user to enter their billing address during checkout.', 'sc' ) .
( class_exists( 'Stripe_Checkout_Pro' ) ? '<br/><p class="description">' . __( 'See below if you also need to require a shipping address.', 'sc' ) . '</p>' : '' ),
'type' => 'checkbox'
),
'verify_zip' => array(
'id' => 'verify_zip',
'name' => __( 'Verify Zip Code', 'sc' ),
'desc' => __( 'Verifies the zip code of the card.', 'sc' ),
'type' => 'checkbox'
),
'enable_remember' => array(
'id' => 'enable_remember',
'name' => __( 'Enable "Remember Me"', 'sc' ),
'desc' => __( 'Adds a "Remember Me" option to the checkout form to allow the user to store their credit card for future use with other sites using Stripe. ', 'sc' ) .
sprintf( '<a href="%s" target="_blank">%s</a>', 'https://stripe.com/checkout/info', __( 'See how it works', 'sc' ) ),
'type' => 'checkbox'
),
'use_bitcoin' => array(
'id' => 'use_bitcoin',
'name' => __( 'Enable Bitcoin', 'sc' ),
'desc' => sprintf( __( 'Enable accepting <a href="%s" target="_blank">Bitcoin</a> as a payment option.', 'sc' ), 'https://stripe.com/docs/guides/bitcoin' ),
'type' => 'checkbox'
),
'disable_css' => array(
'id' => 'disable_css',
'name' => __( 'Disable Plugin CSS', 'sc' ),
'desc' => __( 'If this option is checked, this plugin\'s CSS file will not be referenced.', 'sc' ),
'type' => 'checkbox'
),
'always_enqueue' => array(
'id' => 'always_enqueue',
'name' => __( 'Always Enqueue Scripts & Styles', 'sc' ),
'desc' => __( 'Enqueue this plugin\'s scripts and styles on every post and page.', 'sc' ) . '<br/>' .
'<p class="description">' . __( 'Useful if using shortcodes in widgets or other non-standard locations.', 'sc' ) . '</p>',
'type' => 'checkbox'
),
'uninstall_save_settings' => array(
'id' => 'uninstall_save_settings',
'name' => __( 'Save Settings', 'sc' ),
'desc' => __( 'Save your settings when uninstalling this plugin.', 'sc' ) . '<br/>' .
'<p class="description">' . __( 'Useful when upgrading or re-installing.', 'sc' ) . '</p>',
'type' => 'checkbox'
)
),
/* Keys settings */
'keys' => array(
'enable_live_key' => array(
'id' => 'enable_live_key',
'name' => __( 'Test or Live Mode', 'sc' ),
'desc' => '<p class="description">' . __( 'Toggle between using your Test or Live API keys.', 'sc' ) . '</p>',
'type' => 'toggle_control'
),
'note' => array(
'id' => 'api_key_note',
'name' => '',
'desc' => sprintf( '<a href="%s" target="_blank">%s</a>', 'https://dashboard.stripe.com/account/apikeys', __( 'Find your Stripe API keys here', 'sc' ) ),
'type' => 'section'
),
'test_secret_key' => array(
'id' => 'test_secret_key',
'name' => __( 'Test Secret Key', 'sc' ),
'desc' => '',
'type' => 'text',
'size' => 'regular-text'
),
'test_publish_key' => array(
'id' => 'test_publish_key',
'name' => __( 'Test Publishable Key', 'sc' ),
'desc' => '',
'type' => 'text',
'size' => 'regular-text'
),
'live_secret_key' => array(
'id' => 'live_secret_key',
'name' => __( 'Live Secret Key', 'sc' ),
'desc' => '',
'type' => 'text',
'size' => 'regular-text'
),
'live_publish_key' => array(
'id' => 'live_publish_key',
'name' => __( 'Live Publishable Key', 'sc' ),
'desc' => '',
'type' => 'text',
'size' => 'regular-text'
)
)
);
$sc_settings = apply_filters( 'sc_settings', $sc_settings );
$sc_settings_title = '';
foreach( $sc_settings as $setting => $option ) {
if( false == get_option( 'sc_settings_' . $setting ) ) {
add_option( 'sc_settings_' . $setting );
}
add_settings_section(
'sc_settings_' . $setting,
apply_filters( 'sc_settings_' . $setting . '_title', $sc_settings_title ),
'__return_false',
'sc_settings_' . $setting
);
foreach ( $sc_settings[$setting] as $option ) {
add_settings_field(
'sc_settings_' . $setting . '[' . $option['id'] . ']',
$option['name'],
function_exists( 'sc_' . $option['type'] . '_callback' ) ? 'sc_' . $option['type'] . '_callback' : 'sc_missing_callback',
'sc_settings_' . $setting,
'sc_settings_' . $setting,
sc_get_settings_field_args( $option, $setting )
);
}
register_setting( 'sc_settings_' . $setting, 'sc_settings_' . $setting, 'sc_settings_sanitize' );
$sc_options = array_merge( $sc_options, is_array( get_option( 'sc_settings_' . $setting ) ) ? get_option( 'sc_settings_' . $setting ) : array() );
}
update_option( 'sc_settings_master', $sc_options );
}
add_action( 'admin_init', 'sc_register_settings' );
原因是你需要执行createHero()才能初始化英雄对象。
进一步说明这一点,你在CharBuilder中初始化CharBuilder,当我们从面向对象的角度考虑时,这不是一个好习惯。一种替代方法是在此处使用singleton模式。
答案 3 :(得分:1)
正如已经指出的那样,您没有调用createHero
,它会生成CharBuilder
返回getHero
的实例。因此返回null
值。
这个问题似乎源于对建筑师应该做什么的误解。建筑商应该采取原材料并建造一些东西,它不应该自己返回它的副本。
例如......
public class CharBuilder {
static public Random randNum = new Random();
private String mCharacterName;
private int mStrength = 6;
private int mIntelligence = 6;
private int mConstitution = 6;
private int mDexterity = 6;
private int mHitPoints = 40;
private int mManaPoints = 40;
private String mCharClass;
private String classType;
public Character createHero() {
// Valid the properties you have been given...
if ("warrior".equalsIgnoreCase(classType)) {
mCharClass = "warrior";
mStrength = mStrength + 3;
mIntelligence = mIntelligence - 1;
mConstitution = mConstitution + 4;
mDexterity = mDexterity + 1;
mHitPoints = mHitPoints + 20;
mManaPoints = mManaPoints - 10;
} else if ("Wizard".equalsIgnoreCase(classType)) {
mCharClass = "wizard";
mStrength = (mStrength - 1);
mIntelligence = (mIntelligence + 3);
mConstitution = (mConstitution + 2);
mDexterity = (mDexterity);
mHitPoints = (mHitPoints - 10);
mManaPoints = (mManaPoints + 30);
} else if ("thief".equalsIgnoreCase(classType) || "thievery".equalsIgnoreCase(classType)) {
mCharClass = "thief";
mStrength = (mStrength + 2);
mIntelligence = (mIntelligence + 1);
mConstitution = (mConstitution + 1);
mDexterity = (mDexterity + 5);
mHitPoints = (mHitPoints + 10);
mManaPoints = (mManaPoints + 10);
} else {
throw new UnsupportedOperationException("Unknown class");
}
return new DefaultCharacter(mCharacterName, mStrength, mIntelligence, mConstitution, mDexterity, mHitPoints, mManaPoints, mCharClass);
}
public CharBuilder setCharacterName(String mCharacterName) {
this.mCharacterName = mCharacterName;
return this;
}
public CharBuilder setStrength(int mStrength) {
this.mStrength = mStrength;
return this;
}
public CharBuilder setIntelligence(int mIntelligence) {
this.mIntelligence = mIntelligence;
return this;
}
public CharBuilder setConstitution(int mConstitution) {
this.mConstitution = mConstitution;
return this;
}
public CharBuilder setDexterity(int mDexterity) {
this.mDexterity = mDexterity;
return this;
}
public CharBuilder setHitPoints(int mHitPoints) {
this.mHitPoints = mHitPoints;
return this;
}
public CharBuilder setManaPoints(int mManaPoints) {
this.mManaPoints = mManaPoints;
return this;
}
public CharBuilder setCharClass(String mCharClass) {
this.mCharClass = mCharClass;
return this;
}
public CharBuilder setClassType(String classType) {
this.classType = classType;
return this;
}
}
您可以使用方法链来更容易调用,例如
Character character = new CharBuilder().
setCharClass("Wizard").
setCharacterName("Bob").
setConstitution(10).
setDexterity(10).
setHitPoints(10).
setIntelligence(10).
setManaPoints(10).
setStrength(10).
createHero();
构建者不应该向用户提问,这些信息应该已经获得并且只是提供给构建者。你应该只调用你需要的方法来构建字符,所以上面例子中的许多方法可能会被省略而不支持默认值
Character character = new CharBuilder().
setCharClass("Wizard").
setCharacterName("Bob").
createHero();
构建器应该验证它已经给出的属性,如果缺少一个或者必需的属性(如名称或类),则抛出Exception
我个人喜欢使用接口而不是实现,它允许您定义对象可以拥有的公共合同,例如......
public interface Character {
public String getCharacterName();
public int getStrength();
public int getIntelligence();
public int getConstitution();
public int getDexterity();
public int getHitPoints();
public int getanaPoints();
public String getCharClass();
}
可以用
包裹public class DefaultCharacter implements Character {
private final String mCharacterName;
private final int mStrength;
private final int mIntelligence;
private final int mConstitution;
private final int mDexterity;
private final int mHitPoints;
private final int mManaPoints;
private final String mCharClass;
public Character(String mCharacterName, int mStrength, int mIntelligence, int mConstitution, int mDexterity, int mHitPoints, int mManaPoints, String mCharClass) {
this.mCharacterName = mCharacterName;
this.mStrength = mStrength;
this.mIntelligence = mIntelligence;
this.mConstitution = mConstitution;
this.mDexterity = mDexterity;
this.mHitPoints = mHitPoints;
this.mManaPoints = mManaPoints;
this.mCharClass = mCharClass;
}
public String getCharacterName() {
return mCharacterName;
}
public int getStrength() {
return mStrength;
}
public int getIntelligence() {
return mIntelligence;
}
public int getConstitution() {
return mConstitution;
}
public int getDexterity() {
return mDexterity;
}
public int getHitPoints() {
return mHitPoints;
}
public int getManaPoints() {
return mManaPoints;
}
public String getCharClass() {
return mCharClass;
}
}
现在,因为CharBuilder
只会说它会返回Character
,所以无论如何都可以更改物理实现
通过这种方式,很难遇到您遇到的问题,因为构建器将返回有效的Character
或抛出Exception
详细了解Builder Pattern了解更多详情